FormData 未正确从 React 发送到 Express 服务器。请求正文为空

问题描述 投票:0回答:2

我正在将表单数据从我的 React 应用程序发送到本地主机快递服务器。我已经确保我要发送的 formData 已填充在客户端,但由于某种原因,req.body 在服务器端始终是空对象。我尝试使用标头传输一些数据来检查是否正在发送请求,是的,我可以从服务器端的请求标头访问数据。只是身体是空的。 下面是发送请求的客户端代码

const handleRegister = async (
  setDisabled: React.Dispatch<React.SetStateAction<boolean>>,
  values: InitialValues,
  pictureFile: File,
  resetForm: (
    nextState?: Partial<FormikState<InitialValues>> | undefined
  ) => void,
  uri: string
) => {
  const formData = new FormData();

  Object.keys(values).map((key) => {
    if (key === "confirm_password") return;
    formData.append(key, values[key]);
  });

  formData.append("picture", pictureFile);
  formData.append("picturePath", pictureFile.name);
  const rawData = await fetch(`${uri}/auth/register`, {
    method: "POST",
    headers: {
      "Cache-Control": "no-cache",
      email: values.email,
    },
    body: formData,
  });

  const jsonData = await rawData.json();
  // Always empty
  console.log(jsonData);
};

我正在使用 formik,并且 formData 已正确填充,我已经确定了这一点。

下面是我的服务器端代码。

import express from "express";
import multer from "multer";
import cors from "cors";
import bodyParser from "body-parser";
import dotenv from "dotenv";
import morgan from "morgan";
import helmet from "helmet";
import mongoose from "mongoose";
import checkRouter from "./routes/checkRouter";
import authRouter from "./routes/authRouter";
import { register } from "./controllers/auth";
import checkExistingUser from "./middlewares/checkExistingUser";
import getRandomMiliseconds from "./utils/getRandomMiliseconds";

const app = express();
app.use(cors());
app.use(morgan("common"));
app.use(helmet());
app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));
app.use(bodyParser.json({ limit: "30mb" }));
app.use(bodyParser.urlencoded({ limit: "30mb", extended: true }));
dotenv.config();

app.use("/assets", express.static("public"));

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "public/");
  },
  filename: (req, file, cb) => {
    const randomizedNumber = getRandomMiliseconds();
    cb(null, req.body.email + "-" + file.originalname + "-" + randomizedNumber);
  },
});

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

app.use("/check", checkRouter);
app.use("/auth", authRouter);

// app.post(
//   "/auth/register",
//   checkExistingUser,
//   // uploadMiddleWare.single("picture"),
//   register
// );

// In here the req.body is always empty.
app.post("/auth/register", (req, res) => {
  console.log(req.body);
  res.status(200).json(req.body);
});

mongoose.connect("mongodb://127.0.0.1:27017/SweeterDB").then(() => {
  app.listen(3001, async () => {
    console.log("Server started, listening at port 3001");
  });
});

reactjs express form-data
2个回答
0
投票

将uploadMiddleWare移到需要访问请求体的路由之前:

// ...
app.use(uploadMiddleWare.single("picture"));
app.use("/check", checkRouter);
app.use("/auth", authRouter);
// ...

或者您可以更新注册路由以使用 uploadMiddleWare.single 中间件用于图片字段:

app.post("/auth/register", uploadMiddleWare.single("picture"), checkExistingUser, register);

通过将 uploadMiddleWare 放置在 /auth/register 路由之前,您可以允许 multer 处理 FormData 并使用非文件字段填充 req.body。 checkExistingUser 和注册中间件现在应该能够访问 req.body 中的数据。


0
投票

问题似乎在于您在 Express 服务器中处理多部分/表单数据的方式。当您使用 bodyParser.json() 中间件时,它仅解析请求正文中的 JSON 数据,而不解析表单数据。要处理 multipart/form-data,您应该使用 multer 中间件来解析表单数据并使其在 req.body 中可用。

如果尚未安装 multer 软件包,请安装:

npm install multer

这里如何修改服务器端代码以正确使用 multer:

import express from "express";
import multer from "multer";
import cors from "cors";
import dotenv from "dotenv";
import morgan from "morgan";
import helmet from "helmet";
import mongoose from "mongoose";
import checkRouter from "./routes/checkRouter";
import authRouter from "./routes/authRouter";
import { register } from "./controllers/auth";
import checkExistingUser from "./middlewares/checkExistingUser";
import getRandomMiliseconds from "./utils/getRandomMiliseconds";

const app = express();
app.use(cors());
app.use(morgan("common"));
app.use(helmet());
app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));
dotenv.config();

app.use("/assets", express.static("public"));

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "public/");
  },
  filename: (req, file, cb) => {
    const randomizedNumber = getRandomMiliseconds();
    cb(null, req.body.email + "-" + file.originalname + "-" + randomizedNumber);
  },
});

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

app.use("/check", checkRouter);
app.use("/auth", authRouter);

app.post(
  "/auth/register",
  checkExistingUser,
  uploadMiddleWare.single("picture"), // Use multer middleware to handle form data
  register
);

mongoose.connect("mongodb://127.0.0.1:27017/SweeterDB").then(() => {
  app.listen(3001, async () => {
    console.log("Server started, listening at port 3001");
  });
});

通过此修改,multer 将正确处理 multipart/form-data,并且您将能够按照注册函数和其他路由处理程序中的预期访问 req.body。

© www.soinside.com 2019 - 2024. All rights reserved.