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
相关产品推荐
相关产品推荐

