Node.js接收POST文件上传时req.body为空对象{}问题排查
问题场景
在Node.js服务中接收POST方式上传的文件时,出现req.body为空对象{}、req.files为undefined的异常,相关实现代码如下:
前端代码(React - FileUploader.js)
// React - FileUploader.js const handleSubmission = (e) => { e.preventDefault(); if(isSelected === false){ alert("load the file"); } else{ const formData = new FormData(); formData.append("certificate",selectFile); // API CALL fetch("http://localhost:8080/upload", { method: "POST", body: formData, headers : { "Content-Type" : "multipart/form-data" } }).then((response) =>response.json()) .then((result)=>{ console.log("Success : ", result); }) .catch((error)=>{ console.error("Error : ",error); }); } };
服务端代码(Node.js - Server.js)
app.use(cors()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended : true})); app.post('/upload', async function(req ,res){ try { const file = req.files; // undefined const bodyData = req.body; // {} console.log("file : ",file); console.log("bodyData : ",bodyData); res.status(200).send({ message: "FILE RECEIVED!" }); } catch(error){ res.send("ERROR") }; });
问题说明
目前已尝试使用Multer处理multipart格式请求但仍得到相同结果;根据MDN文档说明,FormData并非普通对象,是专为XMLHttpRequest/fetch传输设计的特殊对象,无法通过常规console.log直接打印解析其内容。现需排查该场景下Node.js服务端无法正常解析请求体、获取上传文件的具体原因与修复方案。
问题根因
- 前端手动写死
Content-Type请求头:提交FormData时,浏览器会自动生成携带正确boundary(报文分割边界)的multipart/form-data请求头,手动设置该头会丢失boundary参数,服务端无法正确拆分请求报文内容,直接导致解析失败。 - 服务端Multer配置/挂载错误:
body-parser本身不支持解析multipart/form-data格式的请求,即使安装了Multer,如果没有将Multer解析中间件正确挂载到对应上传路由上,请求依然不会被解析,req.body和req.files自然为空。 - 字段匹配错误:Multer配置的文件字段名如果和前端FormData append的字段名不一致,也无法正确读取到上传的文件。
修复方案
前端修复
删除fetch请求中手动设置的Content-Type请求头,交由浏览器自动补全带正确boundary的请求头,修正后的请求代码如下:
fetch("http://localhost:8080/upload", { method: "POST", body: formData // 移除手动配置的headers项,不要手动设置Content-Type }).then((response) =>response.json()) .then((result)=>{ console.log("Success : ", result); }) .catch((error)=>{ console.error("Error : ",error); });
服务端修复
- 安装Multer依赖:执行命令
npm install multer - 引入Multer并完成配置,将Multer解析中间件挂载到上传路由上,确保配置的文件字段名和前端传递的
certificate字段一致,修正后的服务端核心代码如下:
const express = require('express'); const cors = require('cors'); const bodyParser = require('body-parser'); const multer = require('multer'); const app = express(); // 配置Multer存储方式,示例为内存存储,可根据需求替换为磁盘存储 const upload = multer({ storage: multer.memoryStorage() }); app.use(cors()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended : true})); // 单文件上传使用upload.single,参数对应前端FormData的文件字段名 app.post('/upload', upload.single('certificate'), async function(req ,res){ try { const file = req.file; // 单文件上传时,文件信息挂载在req.file,多文件上传使用req.files const bodyData = req.body; // 表单内普通字段会被解析到req.body console.log("file : ",file); console.log("bodyData : ",bodyData); res.status(200).send({ message: "FILE RECEIVED!" }); } catch(error){ res.status(500).send("ERROR") }; }); app.listen(8080, () => { console.log('Service started on port 8080'); });
补充说明:如果需要支持多文件上传,可将
upload.single('certificate')替换为upload.array('certificate', 最大允许上传数量),此时所有上传的文件信息会以数组形式挂载在req.files上。
内容的提问来源于stack exchange,提问作者Kite_Z
相关产品推荐
相关产品推荐

