React前端POST请求Body为空问题(Postman可正常请求)
问题
搭建了React前端 + Express-Prisma Node.js后端架构,用Postman发送content-type: x-www-form-urlencoded的POST请求能正常执行,但前端通过Axios发起请求时,后端无法获取请求Body中的数据。
前端Axios POST代码
async function acceptCreateTask() { const createTaskFormData = new FormData(); createTaskFormData.append("title", formValue.title); createTaskFormData.append("category", formValue.category); createTaskFormData.append("discription", formValue.discription); try { const response = await axios({ method: "post", url: "http://localhost:3001/task", data: createTaskFormData, headers: { "content-type": "application/x-www-form-urlencoded" }, }).then((res) => { // }); } catch (error) { // } }
后端Express-Prisma处理代码
const { PrismaClient } = require("@prisma/client"); const prisma = new PrismaClient(); var cors = require("cors"); var express = require("express"); var app = express(); app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); //create a task app.post("/task", async (req, res) => { console.log(req.body); const taskTitle = req.body.title; const taskCategory = req.body.category; const taskDiscription = req.body.discription; if (!req.body || !taskTitle || !taskCategory || !taskDiscription) { return res .status(400) .json({ message: "Title, categoy or discription is missing" }); } try { const message = "Task created successfully"; await prisma.task.create({ data: { title: taskTitle, category: taskCategory, discription: taskDiscription, }, }); return res.json({ message }); } catch (e) { return res.status(500).json({ message: "something went wrong" }); } });
原因分析
核心矛盾在于请求体格式与content-type头不匹配:
- 用
FormData构造请求体时,它默认对应multipart/form-data类型,但手动设置了x-www-form-urlencoded头,导致后端的express.urlencoded中间件无法解析这种混合格式的请求。 - Postman能正常工作是因为直接构造了标准的
x-www-form-urlencoded键值对,和后端解析逻辑完全匹配。
解决方案
方案一:使用URLSearchParams适配x-www-form-urlencoded格式
修改前端代码,用URLSearchParams代替FormData,它会自动生成符合x-www-form-urlencoded规范的请求体,Axios也会自动设置正确的请求头:
async function acceptCreateTask() { const params = new URLSearchParams(); params.append("title", formValue.title); params.append("category", formValue.category); params.append("discription", formValue.discription); try { const response = await axios.post("http://localhost:3001/task", params); // 处理响应逻辑 } catch (error) { // 处理错误逻辑 } }
后端代码无需修改,保持原有的express.urlencoded({ extended: true })即可。
方案二:后端支持multipart/form-data格式(保留FormData)
如果需要继续使用FormData,需在后端添加multer中间件解析multipart/form-data类型的请求:
- 安装multer依赖:
npm install multer
- 修改后端代码:
const { PrismaClient } = require("@prisma/client"); const prisma = new PrismaClient(); var cors = require("cors"); var express = require("express"); var multer = require("multer"); var app = express(); // 配置multer,仅解析字段不保存文件 const upload = multer({ storage: multer.memoryStorage() }); app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // 用upload.none()解析FormData中的文本字段 app.post("/task", upload.none(), async (req, res) => { console.log(req.body); const taskTitle = req.body.title; const taskCategory = req.body.category; const taskDiscription = req.body.discription; if (!req.body || !taskTitle || !taskCategory || !taskDiscription) { return res .status(400) .json({ message: "Title, category or discription is missing" }); } try { const message = "Task created successfully"; await prisma.task.create({ data: { title: taskTitle, category: taskCategory, discription: taskDiscription, }, }); return res.json({ message }); } catch (e) { return res.status(500).json({ message: "something went wrong" }); } });
- 前端去掉手动设置的
content-type头,让Axios自动处理:
async function acceptCreateTask() { const createTaskFormData = new FormData(); createTaskFormData.append("title", formValue.title); createTaskFormData.append("category", formValue.category); createTaskFormData.append("discription", formValue.discription); try { const response = await axios.post("http://localhost:3001/task", createTaskFormData); // 处理响应逻辑 } catch (error) { // 处理错误逻辑 } }
内容的提问来源于stack exchange,提问作者Craws
相关产品推荐
相关产品推荐

