Node.js使用multer上传文件遇异常:/update路由报错,仅uploadArray可用
嘿,我来帮你搞定这个multer上传的问题!你遇到的SyntaxError: Unexpected token < in JSON at position 0错误,本质是后端返回了HTML格式的错误内容,但前端期望解析JSON,所以才会报这个错。结合你的代码,咱们一步步排查修复:
1. 先把multer的错误处理改对
你现在的upload和uploadArray中间件里,遇到错误只是打个日志就直接next(),这会让错误跑到Express默认的错误处理器,它返回的是HTML页面(开头就是<),这就是前端解析失败的根源。
修改/utils/lib/account.js里的错误处理逻辑:
exports.upload = (req, res, next) => { upload(req, res, function (err) { if (err) { console.log(err); // 直接返回JSON格式的错误,不让错误继续扩散 return res.status(400).json({message: '文件上传失败', error: err.message}); } next(); }); }; exports.uploadArray = (req, res, next) => { uploadArray(req, res, function (err) { if(err){ console.log(err); return res.status(400).json({message: '文件上传失败', error: err.message}); } next(); }); };
2. 确认前端请求的Content-Type没搞错
用fields方式上传文件时,前端必须把请求的Content-Type设为multipart/form-data,绝对不能用application/json。如果前端错发了JSON格式的请求,multer根本解析不了文件和字段,会导致后续操作出错。
3. 调整update_profile控制器的文件处理逻辑
fields和array方式下,req.files的结构完全不一样:
array模式:req.files是一个数组,每个元素是上传的文件fields模式:req.files是个对象,键是你定义的photo和cover,每个键对应一个长度为1的数组(因为你设了maxCount:1)
你之前的new控制器是针对array写的,如果update_profile直接复用了相同的逻辑,肯定会出错。给你一个适配fields的处理示例:
// update_profile控制器里的文件处理逻辑 const uri = new DataUri(); const promises = []; const images = {}; // 用对象分别存photo和cover的URL // 处理photo字段(如果有上传) if (req.files?.photo) { const photoFile = req.files.photo[0]; uri.format('.png', photoFile.buffer); promises.push( new Promise((resolve, reject) => { cloudinary.v2.uploader.upload(uri.content, (error, result) => { if (error) reject(error); images.photo = result.url; resolve(); }); }) ); } // 处理cover字段(如果有上传) if (req.files?.cover) { const coverFile = req.files.cover[0]; uri.format('.png', coverFile.buffer); promises.push( new Promise((resolve, reject) => { cloudinary.v2.uploader.upload(uri.content, (error, result) => { if (error) reject(error); images.cover = result.url; resolve(); }); }) ); } // 等待所有文件上传完成后执行更新 Promise.all(promises) .then(() => { // 合并上传的图片URL和表单字段 const updateData = { ...req.body, ...images }; // 执行你的更新操作,比如用findByIdAndUpdate Account.findByIdAndUpdate(req.body.id, updateData, { new: true }) .then(updatedAccount => { res.json({ message: '更新成功', type: 'success', code: 200, data: updatedAccount }); }) .catch(err => { res.status(500).json({ message: '更新失败', error: err.message }); }); }) .catch(err => { console.log(err); res.status(400).json({ message: '文件上传失败', error: err.message }); });
4. 优化路由中间件的应用范围
你现在给/update路由用了.all(helper.upload),这会把multer中间件应用到所有请求方法(GET、OPTIONS等),但实际上只有POST请求需要处理文件上传。改成这样更合理:
router.route('/update') .all(helper.verifyToken) .post(helper.upload, account.update_profile) // 只在POST请求时应用upload中间件
按这几步调整后,应该就能解决你的问题了!
内容的提问来源于stack exchange,提问作者JEEZSUSCRIZE
相关产品推荐
相关产品推荐

