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

Express.js大文件下载时浏览器冻结卡顿问题求助

大型CSV文件下载导致浏览器卡顿/冻结的问题

使用Node.js Express服务器下载大型CSV文件时,浏览器偶尔会出现冻结/卡顿情况,用res.sendFile()或res.download()都会触发该问题,且浏览器网络面板未报告任何错误。请问是否遗漏了关键配置?


服务端代码

try {
    res.setHeader('Content-type', 'text/csv');
    res.setHeader("Content-Disposition", `attachment;filename=${filename}`);
    res.sendFile(filename); 
}
catch (e) {
    console.log(e);
    res.send(e).end(); //ERROR
    return;
}

客户端代码

let anchorElement = document.createElement('a');
anchorElement.href = '/report/' + report_id + '/download';
anchorElement.download = export_filename;
anchorElement.target = '_blank';
document.body.appendChild(anchorElement);
anchorElement.click();

浏览器表现

Chrome浏览器

Chrome浏览器下载卡顿状态

Firefox浏览器

Firefox浏览器下载卡顿状态


解决方案建议

1. 改用流式传输,避免一次性加载文件到内存

res.sendFile()默认会把整个文件读入内存再发送,大文件会占用大量服务器内存,同时导致浏览器接收数据时卡顿。改用流式读取分块发送:

const fs = require('fs');
const path = require('path');

try {
    const filePath = path.resolve(filename);
    res.setHeader('Content-Type', 'text/csv');
    res.setHeader('Content-Disposition', `attachment;filename=${path.basename(filePath)}`);
    res.setHeader('Transfer-Encoding', 'chunked'); // 开启分块传输

    const readStream = fs.createReadStream(filePath);
    readStream.pipe(res);

    readStream.on('error', (err) => {
        console.error(err);
        res.status(500).send('文件读取失败').end();
    });
} catch (e) {
    console.error(e);
    res.status(500).send(e).end();
}

2. 添加Content-Length头,让浏览器精准预估进度

提前获取文件大小并设置响应头,浏览器可以更清晰展示下载进度,减少卡顿感知:

const stats = fs.statSync(filePath);
res.setHeader('Content-Length', stats.size);

3. 优化客户端触发逻辑

使用_blank打开新标签会额外占用浏览器资源,改用fetch流式处理Blob,减少资源占用:

fetch('/report/' + report_id + '/download')
    .then(response => response.blob())
    .then(blob => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = export_filename;
        document.body.appendChild(a);
        a.click();
        setTimeout(() => {
            document.body.removeChild(a);
            URL.revokeObjectURL(url); // 释放Blob资源
        }, 0);
    })
    .catch(err => console.error('下载失败:', err));

4. 开启服务器压缩(可选)

用compression中间件开启Gzip压缩,减少传输数据量,提升下载效率:

const compression = require('compression');
app.use(compression());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:54:55