使用multer上传文件时req.body为空、req.files为undefined如何解决
Multer单文件上传时req.body为空、req.files为undefined问题修复
核心问题根因
一共三个直接触发问题的错误,另有两个潜在bug:
- 请求方法使用错误:文件上传携带FormData时使用了GET请求,HTTP规范中GET请求不支持携带请求体,浏览器、Node服务端默认会丢弃GET请求的body内容,这是数据接收不到的最核心原因。你项目里其他正常运行的多文件上传接口,必然是使用POST/PUT等支持请求体的方法,所以可以正常解析。
- 单文件上传取值逻辑错误:使用
multer.single('photo')配置单文件上传时,解析出的文件会挂载在req.file属性上,req.files仅在使用multer.array()/multer.fields()做多文件上传时才会赋值,直接访问req.files['photo']会因为req.files为undefined报错。 - 文件名生成逻辑存在覆盖风险:随机数生成逻辑写在路由初始化外层,服务启动后仅会生成一次随机值,后续所有上传文件共用同一个前缀,仅靠时间戳区分文件名,高并发场景下同毫秒上传的文件会出现重名覆盖。
- SQL返回逻辑错误:UPDATE语句执行后返回的是操作统计对象,不是用户数据列表,原代码直接遍历返回结果拿用户信息的逻辑永远不会触发。
- 注意:axios发送FormData时不需要手动设置
Content-Type: multipart/form-data请求头,手动设置会导致缺失自动生成的boundary分隔符,反而会让multer解析失败。
分步修复方案
1. 修正前后端请求方法
后端路由把GET改为POST:
// 原代码 router.get('/upload-photo', upload, (req, res) => { router.post('/upload-photo', upload, (req, res) => { // 路由逻辑 })
前端axios请求把get改为post:
axios // 原代码 .get(`/api/user/upload-photo`, photoData) .post(`/api/user/upload-photo`, photoData) .then((res) => { dispatch(getPhotos()); }) // 后续catch逻辑保持不变
2. 修正单文件取值逻辑
路由内的文件取值从req.files改为req.file:
const id = req.body.id; // 原代码 const photo = req.files['photo'][0].filename; const photo = req.file.filename;
3. 修复文件名重名风险
把随机数生成逻辑移到filename回调内部,保证每次上传都生成新的随机前缀:
const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, './client/public/images'); }, filename: function (req, file, cb) { // 每次上传重新生成随机数 const random = Math.floor(Math.random() * 100000) + 10000; cb(null, random.toString() + new Date().getTime() + '.jpg'); }, });
4. 修正UPDATE语句的返回逻辑
UPDATE执行后通过affectedRows判断是否更新成功,成功后重新查询对应用户信息返回:
db.query( 'UPDATE users SET photo = ? WHERE id = ?', [photo, id], function (err, result) { if (err) throw err; if (result.affectedRows >= 1) { // 更新成功后查询对应用户信息 db.query('SELECT id, photo FROM users WHERE id = ?', [id], function (queryErr, userRows) { if (queryErr) throw queryErr; res.json(userRows[0]); }) } else { return res.status(200).json({}); } } );
内容的提问来源于stack exchange,提问作者SaLii
相关产品推荐
相关产品推荐

