Next.js POST提交FormData时req.file/req.body返回undefined如何解决
问题根因
req.file、req.body.description返回undefined,且req.body输出原始multipart报文的问题,由两个错误配置共同导致:
- 前端手动设置了
Content-Type: multipart/form-data请求头:发送FormData时浏览器会自动生成带boundary边界参数的合法Content-Type头,手动设置会覆盖掉必填的boundary参数,直接导致后端无法识别报文分割规则 - Next.js内置API路由默认的bodyParser仅支持解析JSON、x-www-form-urlencoded格式的请求体,原生不支持解析multipart/form-data格式,没有经过解析的请求体自然无法直接读取文件和普通字段值。
修复方案
1. 修正前端请求代码
删除fetch配置中手动添加的Content-Type请求头,其余逻辑保持不变:
const res = await fetch('/api/uploadImg', { method: 'POST', // 删除以下headers配置,不要手动设置multipart/form-data头 // headers: { // 'Content-Type': 'multipart/form-data' // }, body: formData });
2. 修正后端API路由逻辑
使用专门的multipart解析库处理请求,这里以适配性更好的formidable为例:
- 安装依赖:
npm install formidable
- 修改
pages/api/uploadImg.js代码,首先关闭默认bodyParser,再用formidable解析表单内容:
import formidable from 'formidable'; import path from 'path'; // 关闭Next.js默认的请求体解析,交给formidable处理multipart报文 export const config = { api: { bodyParser: false, }, }; export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: '请求方法不允许' }); } try { // 配置解析规则 const form = formidable({ uploadDir: path.join(process.cwd(), 'public/uploads'), // 上传文件存储目录,需提前手动创建该文件夹 keepExtensions: true, // 保留文件原始扩展名 }); // 解析请求获取普通字段和文件 const [fields, files] = await new Promise((resolve, reject) => { form.parse(req, (parseErr, parsedFields, parsedFiles) => { if (parseErr) return reject(parseErr); resolve([parsedFields, parsedFiles]); }); }); // formidable默认将字段、文件值包装为数组,取第一个元素即可 const description = fields.description?.[0]; const uploadFile = files.image?.[0]; console.log('描述字段:', description); console.log('上传文件信息:', uploadFile); return res.status(200).json({ success: true, description, fileAccessPath: `/uploads/${path.basename(uploadFile.filepath)}` }); } catch (err) { console.error('上传处理错误:', err); return res.status(500).json({ error: '上传失败' }); } }
注意事项
- 必须提前在项目
public目录下创建uploads文件夹,否则文件写入会触发路径不存在的错误 - 如果你使用Next.js 13+的App Router路由模式,核心逻辑一致:关闭默认的请求体解析,使用formidable等库处理multipart报文即可
- 所有发送FormData的场景都不要手动设置Content-Type头,boundary参数必须由浏览器自动生成才能保证解析正常
内容的提问来源于stack exchange,提问作者Joey Kyber
相关产品推荐
相关产品推荐

