You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
});

服务端修复

  1. 安装Multer依赖:执行命令npm install multer
  2. 引入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:30:47