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

使用Multer上传文件至API失败,req.files为空问题求助

问题诊断与修复方案

核心问题分析

你的代码存在三个关键问题,直接导致req.files始终为空:

1. 前端手动设置请求头错误

axios发送FormData时,绝对不能手动设置Content-Type: multipart/form-data。FormData对象会自动生成包含boundary分隔符的正确请求头,手动设置会丢失这个关键信息,后端multer无法解析文件内容。

2. Multer中间件用法有误

upload.any("photos")的写法不符合规范:any()方法不需要传入字段名参数。如果要精准接收指定字段名的多个文件,应该用upload.array("photos")更合适。

3. File对象有效性存疑

如果你用URL.createObjectURL转换过文件,得到的是字符串而非原生File对象,FormData无法将其识别为文件,后端自然接收不到。必须确保photoArray中的元素是<input type="file">获取的原生File对象。


分步修复代码

前端代码修复

移除手动设置的请求头,确保photoArray元素为真实File对象:

const submitData = async () => {
    const token = Cookies.get("User");

    if (token) {
      const formData = new FormData();

      // 追加普通字段
      formData.append("brand", currentBrand.brand);
      formData.append("model", currentModel);
      // ...其他字段保持不变
      
      // 确保file是<input type="file">获取的原生File对象
      photoArray.forEach((file) => {
        formData.append(`photos`, file);
      });

      await axios
        .post(
          `http://localhost:3000/api/car/create/${
            jwtDecode(token).findUser._id
          }`,
          formData
          // 删除手动设置的headers,axios会自动处理multipart请求头
        )
        .then((res) => {
          setSubmit(true);
          setTimeout(() => {
            setSubmit(false);
          }, 2000);
        })
        .catch((err) => {
          setError({ state: true, message: err.response.data.message });
          setTimeout(() => {
            setError({ state: false, message: "" });
          }, 2000);
        });
    } else {
      setError({ state: true, message: "Must login first" });
      setTimeout(() => {
        setError({ state: false, message: "" });
      }, 2000);
    }
  };

路由代码修复

将upload.any("photos")替换为upload.array("photos"),精准匹配前端传入的字段名:

const router = Router();

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "back/uploads");
    // 注意:必须提前创建back/uploads目录,multer不会自动生成目录
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + file.originalname;
    cb(null, file.fieldname + "-" + uniqueSuffix);
  },
});

const upload = multer({ storage: storage });

// 接收指定字段"photos"的多个文件,第二个参数可设置最大上传数量(可选)
router.post("/create/:id", upload.array("photos"), createCar);

额外检查项

  1. 确认后端项目中back/uploads目录已创建,否则multer会因无法写入文件报错。
  2. 前端photoArray的来源必须正确:如果是通过<input type="file" multiple>选择的文件,应该用event.target.files(FileList对象)转为数组,确保每个元素都是原生File对象,而非URL字符串。

验证修复

重启后端服务后测试:

  • 打开浏览器Network面板,查看请求头的Content-Type是否为multipart/form-data; boundary=xxxxxx(自动生成的分隔符)。
  • 后端控制器中console.log(req.files)会打印出上传的文件数组,包含path、filename等有效信息。

内容的提问来源于stack exchange,提问作者Tecleanu Ionut

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:02:07