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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 22:15:07