Express处理multipart/form-data类型POST请求无法解析表单提交数据问题
我查阅了大量相关问答仍未找到解决方案,对HTTP请求和Express有基础了解,现将相关代码附上说明问题:该功能此前可正常运行,在调整了应用级和路由级中间件后出现异常,无法定位问题点。
客户端代码
<form action="/listings/donations" enctype="multipart/form-data" method="POST">
请求可正常命中对应路由。
应用级中间件
内置请求体解析中间件配置:
app.use(express.urlencoded({ extended: true })) app.use(express.json())
自定义中间件,功能为对所有用户提交的req.body字段值做trim处理:
req.body = _.object(_.map(req.body, function (value, key) { if (value && value.length) { return [key, value.trim()] } else { return [key, value] } }))
trim处理后,在req.body上挂载分页参数:
const perPage = 9 const page = req.query.p || 1 req.body.pagination = { perPage: perPage, page: page }
路由级中间件
新增了magicMiddleware,是运行时拼接的中间件序列,已排除工具本身问题,故障出现在magicMiddleware执行初始阶段:
function magicMiddleware(req, res, next) { const section = req.params[0] const method = req.method const { body } = req // 此处body仅包含{ pagination: { perPage: 9, page: 1 } } !!!!!! }
路由配置如下:
router.post(/^\/(donations|skills|blogs)/, magicMiddleware, async (req, res, next) => { // 后续业务逻辑 })
目前异常为magicMiddleware中拿到的req.body仅包含手动添加的pagination对象,无任何用户提交的POST数据,无法定位问题原因。
问题根因
你的问题是请求体编码格式和解析中间件不匹配导致的:
- 客户端表单使用
multipart/form-data编码提交请求,而Express自带的express.urlencoded仅支持解析application/x-www-form-urlencoded格式的请求体,express.json仅支持解析application/json格式的请求体,二者都不会处理multipart/form-data格式的内容,所以这两个中间件执行完成后,req.body本身就是空对象。 - 后续的trim中间件遍历空的
req.body处理后,依旧是空对象,你再给空对象新增pagination属性,最终到magicMiddleware里自然只能看到pagination这一个字段。
解决方案
根据你的表单场景二选一即可:
场景1:表单包含文件上传
必须使用支持解析multipart/form-data的中间件,最常用的是multer:
- 安装依赖:
npm install multer - 在自定义trim中间件之前,挂载multer中间件:
const multer = require('multer') // 仅解析表单字段、不接收文件用这个配置,如果要接收文件自行调整存储配置 const upload = multer().none() app.use(upload) // 后续再放trim中间件、分页挂载中间件
场景2:表单无文件上传
不需要使用multipart/form-data编码,直接删除form标签上的enctype="multipart/form-data"属性即可,表单默认会使用application/x-www-form-urlencoded编码,express.urlencoded中间件可以正常解析到用户提交的字段。
额外注意
务必保证中间件执行顺序:请求体解析中间件 → 读取/处理req.body的中间件 → 路由中间件,顺序错误永远无法拿到正确的请求体数据。
内容的提问来源于stack exchange,提问作者Curcuma_
相关产品推荐
相关产品推荐

