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

React中使用Fetch上传Excel文件时请求体为空的问题求助

解决React Fetch上传Excel文件时Express服务器req.body为空的问题

Hey there! Let's break down why your file upload isn't working as expected and fix it step by step.

问题核心原因

Express 默认不会解析multipart/form-data格式的请求体,这就是为什么你看到req.body是空对象,且req.files也拿不到文件的原因。之前用form action能成功,是因为浏览器会自动处理表单的编码格式,而Fetch发送的请求需要服务器端专门配置中间件来解析这类数据。

解决方案步骤

1. 后端添加文件上传中间件

你原来的服务器代码里用到了req.files.avatar的写法,正好匹配express-fileupload中间件的用法,我们就用它来处理:

  • 首先安装依赖:
npm install express-fileupload --save
  • 然后在你的Express入口文件(比如app.js)中配置中间件:
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();

// 启用文件上传中间件
app.use(fileUpload());

// 其他基础中间件配置
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 你的上传路由(修正后)
app.post('/upload', function(req, res) {
  console.log(req.files); // 现在能拿到文件对象了!
  try {
    if(!req.files || !req.files.file) { // 注意和前端FormData的key保持一致,你前端用的是'file'
      res.send({
        status: false,
        message: 'No file uploaded'
      });
    } else {
      let excelFile = req.files.file;
      // 将文件移动到uploads目录
      excelFile.mv('./uploads/' + excelFile.name, (err) => {
        if(err) {
          return res.status(500).send(err);
        }
        res.send({
          status: true,
          message: 'File is uploaded',
          data: {
            name: excelFile.name,
            mimetype: excelFile.mimetype,
            size: excelFile.size
          }
        });
      });
    }
  } catch (err) {
    res.status(500).send(err);
  }
})

2. 前端代码优化(可选但更规范)

你的前端代码大部分是对的,不过有几个小细节可以调整:

  • 去掉event.preventDefault():input的onChange事件不需要阻止默认行为
  • 箭头函数定义的fileHandler不需要手动bind(this),因为箭头函数会自动绑定上下文

优化后的前端代码:

class FileUploadComponent extends React.Component {
  fileHandler = (event) => {
    const fileObj = event.target.files[0];
    if (!fileObj) return; // 没有选择文件时直接返回

    const data = new FormData();
    data.append('file', fileObj);

    fetch("/upload", {
      method: 'POST',
      body: data
    }).then(function(response) {
      if (response.status >= 400) {
        throw new Error("Bad response from server");
      }
      return response.json(); // 建议用json解析返回值,更方便处理
    }).then(function(result) {
      console.log("Upload success:", result);
    }).catch(function(err) {
      console.error("Upload failed:", err);
    });
  }

  render() {
    return (
      <input 
        type="file" 
        id="avatar" 
        name="avatar" 
        onChange={this.fileHandler} 
        style={{padding: "10px"}}
        accept=".xlsx,.xls" // 限制只选Excel文件,提升用户体验
      />
    )
  }
}

关键注意点

  • 前端不要手动设置Content-Type: multipart/form-data:Fetch会自动添加这个请求头,并且带上正确的boundary参数,手动设置反而会导致解析失败。
  • 前端FormData的key(这里是'file')要和后端req.files[key]的key完全对应,不然会找不到文件。

内容的提问来源于stack exchange,提问作者Vaibhav Gidde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:42:41