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

FormData无法添加文件至后端问题排查求助

问题:FormData文件无法发送至后端,后端req.body为空、req.files未定义

初始问题:使用console.log(formData.entries())查看时结果为空,后端接收不到文件,文件变量已存在但无法追加到FormData。

更新:通过for循环能看到FormData内容,但后端req.body显示{},req.files为undefined。

前端代码

async function handleMultipleSubmit(event) {
  const formData = new FormData();

  console.log(files);

  files.forEach((file, index) => {
    console.log(file);
    formData.append(`file${index}`, file);
  });

  for (const [ key, value] of formData.entries()) {
    console.log(key, value);
  }

  await axios
    .post("/api/farmers/csv", formData)
    .then((response) => {
      if (response.data.success) {
        console.log(response.data.results);
      } else {
        console.log(response);
      }
    })
    .catch((error) => {
      console.log(error);
    });
}

if (files.length > 0) {
  handleMultipleSubmit();
}
}, [files]);

请求控制台说明

控制台打印显示FormData中已包含多个文件项,键为file0、file1等,对应正常的文件对象。

后端代码

const multer = require("multer");
const fs = require("fs");
const path = require("path");

// 配置multer存储路径和文件名
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "uploads/");
  },
  filename: (req, file, cb) => {
    cb(null, Date.now() + "-" + file.originalname);
  },
});

// 创建multer上传实例
const upload = multer({ storage: storage });

// 自定义文件上传中间件
exports.uploadMiddleware = (req, res, next) => {
  console.log(req);
  console.log(req.body);
  console.log(req.files);
  // 使用multer上传实例
  upload.array("files", 5)(req, res, (err) => {
    if (err) {
      return res.status(400).json({ error: err.message });
    }

    // 获取上传的文件
    const files = req.files;
    const errors = [];

    console.log(files);

    // 验证文件类型和大小
    files.forEach((file) => {
      const allowedTypes = ["text/csv"];
      const maxSize = 5 * 1024 * 1024; // 5MB

      if (!allowedTypes.includes(file.mimetype)) {
        errors.push(`无效文件类型: ${file.originalname}`);
      }

      if (file.size > maxSize) {
        errors.push(`文件过大: ${file.originalname}`);
      }
    });

    // 处理验证错误
    if (errors.length > 0) {
      // 删除已上传的文件
      files.forEach((file) => {
        fs.unlinkSync(file.path);
      });

      return res.status(400).json({ errors });
    }

    // 将文件附加到请求对象
    req.files = files;

    // 进入下一个中间件或路由处理程序
    next();
  });
};

解决方法

1. 统一前后端文件字段名

后端用upload.array("files", 5)表示要接收键名为files的多文件,但前端用file${index}作为键名,导致multer无法识别。修改前端追加文件的代码:

files.forEach((file) => {
  formData.append("files", file);
});

2. 禁止手动设置Axios的Content-Type

Axios会自动为FormData请求生成带boundary的multipart/form-data请求头,手动设置会丢失boundary,导致后端无法解析。当前代码无需额外修改,保持默认即可。

3. 调整后端中间件打印时机

当前在multer解析请求前就打印req.body和req.files,此时还未完成解析,必然为空。把打印代码移到multer解析之后:

exports.uploadMiddleware = (req, res, next) => {
  // 使用multer上传实例
  upload.array("files", 5)(req, res, (err) => {
    if (err) {
      return res.status(400).json({ error: err.message });
    }

    // 解析完成后再打印
    console.log(req.body);
    console.log(req.files);

    // 获取上传的文件
    const files = req.files;
    const errors = [];

    console.log(files);

    // ... 后续验证代码不变
  });
};

4. 确保uploads目录存在

multer指定的uploads/目录如果不存在会报错,在服务启动时自动创建目录:

const uploadDir = path.join(__dirname, "uploads");
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir);
}

内容的提问来源于stack exchange,提问作者Andrew Vargas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 09:35:12