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

React向Node.js服务器传递userId失败问题求助

问题:Node.js服务器无法接收React端传递的userId参数

现象

React端通过FormData传递userId,但服务器端req.body.userId始终返回undefined。手动将服务器代码中的userId设为固定值(如12)时,图片可正常上传至FireStorage对应路径。

服务器端代码(server.js)

const express = require("express");
const multer = require("multer");
const cors = require("cors");
const admin = require("firebase-admin");
const { v4: uuid } = require("uuid");

const serviceAccount = require("./serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  storageBucket: "mydb.firebasestorage.app"
});

const bucket = admin.storage().bucket();

const app = express();
app.use(cors()); // CORS中间件

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

app.get("/upload", (req, res) => {
  res.send(`
    <html>
      <head>
        <title>上传图片</title>
      </head>
      <body>
        <h1>上传图片</h1>
        <form method="POST" action="/upload" enctype="multipart/form-data">
          <input type="file" name="image" accept="image/*" />
          <button type="submit">上传</button>
        </form>
      </body>
    </html>
  `);
});

app.post("/upload", upload.single("image"), async (req, res) => {
  console.log("req.body:", req.body);

  if (!req.file) return res.status(400).send("未上传文件");

  let userId = req.body.userId;
  if (!userId) return res.status(400).send("无效用户ID");

  userId = parseInt(userId, 10);
  if (!Number.isInteger(userId)) return res.status(400).send("无效用户ID");

  try {
    const filename = `upload/${userId}/${uuid()}.png`;
    const file = bucket.file(filename);

    await file.save(req.file.buffer, { resumable: false });
    await file.makePublic();

    const downloadURL = `https://storage.googleapis.com/${bucket.name}/${filename}`;
    res.json({ imageUrl: downloadURL });
  } catch (error) {
    console.error("文件上传错误:", error);
    res.status(500).send("上传失败");
  }
});

app.listen(3000, () => console.log("服务器运行在 http://localhost:3000"));

React端相关代码

const localIP = "我的IPv4地址";
const uploadUrl = `http://${localIP}:3000/upload`;

const [userId, setUserId] = useState(null);


useEffect(() => {
  const fetchUserData = async () => {
    const storedData = localStorage.getItem("auth");
    if (!storedData) return;

    const { email, password } = JSON.parse(storedData);
    try {
      const userResponse = await axios.get(
        `http://localhost:8080/users/byEmail/${email}`,
        {
          headers: { "Content-Type": "application/json" },
          auth: { username: email, password },
        }
      );

      setUserId(parseInt(userResponse.data.id)); // 修正原代码语法错误
      console.log(userResponse.data.id); // 此处输出正常,可获取正确userId
    } catch (error) {
      console.error("获取用户信息失败:", error);
    }
  };

  fetchUserData();
}, []);

const handleFileChange = async (event) => {
  const file = event.target.files[0];
  if (!file) return;

  const allowedTypes = ["image/jpeg", "image/jpg", "image/png"];
  if (!allowedTypes.includes(file.type)) {
    setFileName("无效文件类型!");
    event.target.value = "";
    return;
  }

  if (userId === null) {
    console.error("用户ID无效");
    return;
  }

  try {
    const formData = new FormData();
    formData.append("image", file);
    formData.append("userId", String(userId));

    const response = await fetch(uploadUrl, {
      method: "POST",
      body: formData,
    });

    if (!response.ok) throw new Error("上传出错");

    const data = await response.json();
    setFileName(file.name);
    setResultText(`图片上传成功: ${data.imageUrl}`);
  } catch (error) {
    console.error("错误:", error);
    setFileName("上传失败");
    event.target.value = "";
  }
};

问题修复方案

  1. 修复React端语法错误:原代码中setUserId(parseInt(userResponse.data.id,);缺少闭合括号,导致userId无法正确赋值,修正为setUserId(parseInt(userResponse.data.id));。
  2. 确认请求时机:确保fetchUserData异步请求完成、userId成功赋值后,再触发上传操作(当前代码已有if (userId === null)的判断,可保留)。
  3. 服务器端验证:在服务器端console.log("req.body:", req.body),确认multer是否正常解析表单字段。若req.body为空,需检查multer配置是否正确(当前使用memoryStorage()无问题)。
  4. 避免手动设置请求头:React端使用fetch传递FormData时,不要手动设置Content-Type,FormData会自动生成带边界标识的正确请求头,手动设置会导致服务器解析失败。

内容的提问来源于stack exchange,提问作者Gabi Moldovan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:42:20