fetch POST提交FormData到Express后端时req.body为空对象问题求助
问题根因
- 客户端请求配置错误:发送的是FormData格式的请求体,却手动设置了
Content-type: 'application/json'请求头,同时fetch配置项中字段名应为小写headers而非大写Headers。使用fetch发送FormData时,浏览器会自动生成正确的multipart/form-data请求头并携带边界标识,手动设置请求头会导致格式不匹配,Express的express.json()中间件无法解析请求体。另外客户端请求的路径是/myendpoint,但后端路由挂载的路径是/api/contact,路径不匹配也会导致请求无法到达正确的处理逻辑。 - 后端缺少FormData解析中间件:Express内置的
express.json()仅能解析application/json格式的请求体,无法解析multipart/form-data类型的FormData数据,所以req.body会是空对象。 - 变量解构不匹配:你从
req.body中解构的是value1到value8,但后续拼接邮件模板时使用的是name、email等变量,变量名完全不对应,就算请求体解析成功也会得到undefined。
解决方案(二选一即可)
方案一:保持使用FormData提交
1. 修改客户端代码
移除手动设置的Content-Type头,修正headers字段名和请求路径:
async function formSend(e) { e.preventDefault(); let formData = new FormData(form); try { const res = await fetch('/api/contact', { // 修正请求路径和后端匹配 method: 'POST', body: formData // 不要手动加headers,浏览器会自动处理 }); if (res.ok) { const result = await res.json(); } } catch (error) { alert('error') } };
2. 后端安装配置multer解析FormData
首先安装依赖:npm install multer
修改路由代码:
const multer = require('multer'); const upload = multer().none(); // 仅解析文本字段,不处理文件上传 router.post('/', upload, (req, res) => { // 添加multer中间件 console.log(req.body); // 修改变量解构,字段名和你表单中input的name属性保持一致 const { name, email, phone, category, status, date, witness, message} = req.body; // 后续邮件逻辑保持不变,注意变量名要和解构出来的一致 const output = ` <p>You have a new contact request</p> <h3>Contact Details</h3> <ul> <li>Name: ${name}</li> <li>Email: ${email}</li> <li>Phone: ${phone}</li> <li>Category: ${category}</li> <li>status: ${status}</li> <li>Date: ${date}</li> <li>witness: ${witness}</li> </ul> <h3>Message</h3> <p>${message}</p> `; // 剩余nodemailer逻辑保持不变 });
方案二:改为JSON格式提交(不需要额外安装中间件)
1. 修改客户端代码,将FormData转为JSON格式发送
async function formSend(e) { e.preventDefault(); let formData = new FormData(form); // 将FormData转为普通对象 const formObject = Object.fromEntries(formData.entries()); try { const res = await fetch('/api/contact', { method: 'POST', body: JSON.stringify(formObject), headers: { 'Content-type': 'application/json' } }); if (res.ok) { const result = await res.json(); } } catch (error) { alert('error') } };
2. 修改后端路由的解构逻辑
router.post('/', (req, res) => { console.log(req.body); // 修改变量解构,字段名和你表单中input的name属性保持一致 const { name, email, phone, category, status, date, witness, message} = req.body; // 后续邮件逻辑保持不变 });
内容的提问来源于stack exchange,提问作者Vahe
相关产品推荐
相关产品推荐

