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

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 });
    }
}

问题原因

  1. res.download执行成功时,会自动向客户端发送完整的HTTP响应(包含响应头和文件内容),此时响应流程已结束。在回调中再调用res.status(200).json(),会尝试再次发送响应头,触发"Header Already Sent"错误。
  2. 下载出错时,如果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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:25:10