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

MERN栈项目中如何通过单次按钮点击同时上传图片与表单数据?

MERN栈单请求上传图片+表单数据问题修复

核心问题分析与修复步骤

1. React端Content-Type设置错误

手动设置"Content-Type": "multipart/form-data"会丢失FormData自动生成的boundary分隔符,导致后端multer无法正确解析请求。同时你只向FormData添加了图片,遗漏了其他表单字段,后端req.body会拿不到必填数据。

修复后的React代码:

const URL = "http://localhost:2040/add_recipe";
const formData = new FormData();

// 必须添加所有表单字段,不止图片
formData.append("recipe_image", selectedFile);
formData.append("category", 你的分类字段值); // 替换为实际表单变量
formData.append("ptime", 你的耗时字段值);
formData.append("name", 你的食谱名称字段值);
formData.append("noOfPeople", 你的适用人数字段值);
formData.append("shortDesc", 你的简短描述字段值);
formData.append("recipe", 你的食谱步骤字段值);

let config = {
  headers: {
    // 移除手动设置的Content-Type,axios会自动处理
    authorization: JSON.parse(localStorage.getItem("token")),
  },
};

axios
  .post(URL, formData, config)
  .then((response) => {
    console.log("上传成功:", response.data);
  })
  .catch((error) => {
    console.error("上传失败:", error.response?.data || error.message);
  });

2. 后端全局变量与异常处理问题

全局filePath会在多并发请求时被覆盖,且未处理无文件上传、表单字段不全的场景,部分分支没有返回响应会导致请求挂起。

修复后的后端代码:

const Recipe = require("../models/Recipe");
const fs = require("fs");

const AddRecipe = async (req, res) => {
  // 将filePath移到函数内部,避免全局污染
  let filePath = "";
  if (req.file) {
    filePath = req.file.path;
  }

  console.log("filepath:", filePath);

  try {
    const existingRecipe = await Recipe.findOne({ name: req.body.name });
    if (existingRecipe) {
      return res.json({ Response: "Recipe already exists!" });
    }

    // 解构表单字段,校验必填项
    const { category, ptime, name, noOfPeople, shortDesc, recipe } = req.body;
    if (!category || !ptime || !name || !noOfPeople || !shortDesc || !recipe) {
      return res.json({ Response: "请填写所有必填字段!" });
    }

    const recipeData = {
      category,
      ptime,
      name,
      noOfPeople,
      shortDesc,
      recipe,
    };

    // 仅当存在上传文件时才添加avatar字段
    if (filePath) {
      recipeData.avatar = {
        data: fs.readFileSync(filePath),
        contentType: req.file.mimetype, // 使用文件实际MIME类型,而非固定png
      };
    }

    const newRecipe = await Recipe.create(recipeData);
    if (newRecipe._id) {
      // 可选:上传成功后删除临时文件
      if (filePath) fs.unlinkSync(filePath);
      return res.json({ Response: "Recipe added successfully!" });
    } else {
      return res.json({ Response: "Recipe not added!" });
    }
  } catch (error) {
    console.error("服务器错误:", error);
    return res.status(500).json({ Response: "服务器内部错误!" });
  }
};

module.exports = { AddRecipe };

3. Multer配置补充检查

确保你的multer存储配置正确,且目标目录存在:

const multer = require("multer");
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "./uploads"); // 确保uploads目录已创建,否则会报错
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + "-" + file.originalname);
  },
});

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

内容的提问来源于stack exchange,提问作者Kumar Kelash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:48:50