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

Express中用Node.js文件系统写入POST请求体报错:ERR_HTTP_HEADERS_SENT

问题分析与解决

错误含义

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client 这个错误的核心是:你已经向客户端发送了一次响应(比如调用了res.send),之后又试图再次发送响应或者修改响应头,Node.js不允许重复发送响应。

代码问题

你的/test路由存在异步流程处理错误:

  • fs.writeFile是异步非阻塞操作,调用它之后代码会立刻执行后面的next(),直接进入下一个中间件执行res.send(req.body),提前给客户端发送了响应。
  • 后续如果fs.writeFile执行出错,回调里的next(err)会让Express尝试发送错误响应,但此时响应已经发出去了,必然触发上述错误。
  • 另外,这种写法也会导致客户端在文件写入未完成时就收到响应,无法感知写入是否成功。

修复方案

方案1:调整异步回调的执行顺序

把next()移到fs.writeFile的回调内部,确保文件写入完成(或出错)后再处理后续响应逻辑:

router.post('/test', (req, res, next) => {
  const message = `${req.body.name} sent ${req.body.email} this message: ${req.body.msg}`
  fs.writeFile(path.join(__dirname, 'files', 'msg.txt'), message, (err) => {
    if (err) {
      return next(err)
    } else {
      console.log(message)
      next() // 写入完成后再进入下一个中间件
    }
  })
}, (req, res, next) => {
  res.send(req.body)
});

方案2:使用Promise+async/await简化异步逻辑

利用fs.promises的异步API,配合async/await让代码逻辑更清晰,避免回调嵌套:

router.post('/test', async (req, res, next) => {
  try {
    const message = `${req.body.name} sent ${req.body.email} this message: ${req.body.msg}`
    // 等待文件写入完成
    await fsPromises.writeFile(path.join(__dirname, 'files', 'msg.txt'), message)
    console.log(message)
    // 写入成功后发送响应
    res.send(req.body)
  } catch (err) {
    // 捕获错误并传递给Express错误处理中间件
    next(err)
  }
});

内容的提问来源于stack exchange,提问作者payiyke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:25:21