我正在将表单数据从我的 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");
});
});
将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 中的数据。
问题似乎在于您在 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。