首次使用Multer上传图片失败求助:在线订餐系统产品创建异常
解决Multer上传图片与产品信息不同步的问题
问题根源分析
从代码和报错来看,核心问题出在Multer的文件名配置错误,同时前端请求头设置存在冗余,导致图片上传失败,进而无法关联产品信息。
具体修复步骤
1. 修正后端Multer的文件名配置
在router.js的multer.diskStorage配置中,filename函数存在参数错误:
// 错误代码 filename: (req, file, cb) => { cb(null, req.body, filename); }
这里错误地将req.body(整个请求体对象)作为文件名传入,还引用了未定义的filename变量,导致Multer无法生成合法文件名。修改为:
// 正确代码 filename: (req, file, cb) => { // 使用前端传入的自定义文件名 cb(null, req.body.filename); }
2. 优化前端图片上传请求头
前端上传图片时,无需手动设置Content-Type: multipart/form-data,FormData会自动生成包含boundary的正确请求头,手动设置反而会导致后端无法解析表单数据。修改handleCreateProduct中的图片上传请求:
// 移除headers中的Content-Type设置 await fetch("/upload/image", { headers: { Authorization: `Bearer ${token}`, // 删除这一行:"Content-Type": "multipart/form-data" }, method: "POST", body: formData, });
3. 确保存储目录存在
检查后端项目中的public/images目录是否存在,如果不存在,Multer会抛出文件写入错误。可以手动创建该目录,或者在代码中添加自动创建逻辑:
const fs = require("fs"); const path = require("path"); const storagePath = path.join(__dirname, "../public/images"); if (!fs.existsSync(storagePath)) { fs.mkdirSync(storagePath, { recursive: true }); } // 然后再初始化multer storage const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, storagePath); }, filename: (req, file, cb) => { cb(null, req.body.filename); }, });
可选优化:合并上传请求
当前流程是先上传图片再上传产品信息,存在两次HTTP请求的冗余。可以将产品信息和图片合并到同一个FormData中,一次请求完成所有操作:
前端修改
const handleCreateProduct = async (e) => { e.preventDefault(); try { const formData = new FormData(); let filename = null; // 添加产品文本字段到FormData formData.append("title", title); formData.append("desc", desc); formData.append("category", category); formData.append("price", price); formData.append("review", review); // 添加图片(如果有) if (image) { filename = Date.now() + image.name; formData.append("img", filename); formData.append("image", image); } // 一次请求上传所有数据 const res = await fetch("/product", { headers: { Authorization: `Bearer ${token}`, }, method: "POST", body: formData, }); const food = await res.json(); navigate(`/food/${food._id}`); } catch (error) { console.error(error.message); } };
后端修改
修改产品路由,添加Multer中间件处理图片:
// 替换原产品路由 router.post("/product", verifyTokenAdmin, upload.single("image"), createproductController);
在createproductController中,直接从req.body获取产品文本字段,img字段即为存储的文件名,可直接存入数据库。
内容的提问来源于stack exchange,提问作者user20872939
相关产品推荐
相关产品推荐

