Express中使用res.download出现Header Already Sent问题致服务器崩溃
Express res.download 报 Header Already Sent 错误的解决方案
问题现象
使用Express的res.download方法下载文件时,文件能正常下载,但服务器持续抛出"Header Already Sent"错误并崩溃,相关代码如下:
const getRequestTemplate = async (req, res) => { try { // Call the service function to get the file path const filePath = await getRequestTemplateService(); // Send the file as a response res.download(filePath, 'requestTemplate.xlsx', (err) => { if (err) { // Handle errors here console.error('Error downloading file:', err); res.status(400).json({ statusCode: 400, message: 'Error Downloading Request Template', data: null }); } else { // Send success response if download completes successfully console.log('File downloaded successfully'); // You can send any custom success response here res.status(200).json({ statusCode: 200, message: 'Request Template downloaded successfully', data: null }); } }); } catch (error) { console.error('Error:', error); res.status(500).json({ statusCode: 500, message: 'Error Downloading Request Template', data: null }); } }
问题原因
res.download执行成功时,会自动向客户端发送完整的HTTP响应(包含响应头和文件内容),此时响应流程已结束。在回调中再调用res.status(200).json(),会尝试再次发送响应头,触发"Header Already Sent"错误。- 下载出错时,如果
res.download已经发送了部分响应头,后续调用res.status(400).json()同样会导致重复发送头的问题。
修复方案
- 成功回调中:移除额外的JSON响应,因为
res.download已经完成响应发送。 - 所有错误处理分支:先检查
res.headersSent,确保响应头未发送时再发送错误JSON。
修复后的代码:
const getRequestTemplate = async (req, res) => { try { const filePath = await getRequestTemplateService(); res.download(filePath, 'requestTemplate.xlsx', (err) => { if (err) { console.error('Error downloading file:', err); // 仅在响应头未发送时发送错误响应 if (!res.headersSent) { res.status(400).json({ statusCode: 400, message: 'Error Downloading Request Template', data: null }); } } else { console.log('File downloaded successfully'); // 无需额外发送JSON响应,res.download已完成流程 } }); } catch (error) { console.error('Error:', error); if (!res.headersSent) { res.status(500).json({ statusCode: 500, message: 'Error Downloading Request Template', data: null }); } } }
关键修复点说明
- 移除成功分支的JSON响应:客户端已通过
res.download获取到文件,不需要额外的成功响应,避免重复发送HTTP头。 - 增加
res.headersSent判断:在所有需要发送响应的错误分支中,先确认响应未被发送,再执行响应操作,彻底避免"Header Already Sent"错误。
内容的提问来源于stack exchange,提问作者Riches
相关产品推荐
相关产品推荐

