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

如何限制并提升res.download()方法的文件下载速度

res.download()场景下的下载限速与提速实现方案

下载速度限制实现

原生res.download()是封装好的文件流自动管道方法,没有暴露流写入节奏的控制钩子,要做限速需要手动接管流传输逻辑,有两种成熟实现路径:

  • 应用层单/多连接限速
    基于令牌桶算法做流传输节流,手动创建文件读取流,在文件流和HTTP响应流之间加一层限速转换流,控制单位时间内写入响应的数据量。可以直接用流处理包实现,不需要从零写算法,示例代码:
    const fs = require('fs');
    const Throttle = require('throttle');
    // 单连接限速100KB/s,可根据业务场景动态调整
    const SINGLE_CONNECTION_RATE = 1024 * 100;
    
    app.get('/download', (req, res) => {
      const targetPath = '/data/files/your-target-file.pdf';
      const fileName = '文件.pdf';
      // 手动设置下载响应头
      res.setHeader('Content-Disposition', `attachment; filename=${encodeURIComponent(fileName)}`);
      res.setHeader('Content-Type', 'application/octet-stream');
      // 创建文件流 -> 限速流 -> 响应流的管道
      const fileReadStream = fs.createReadStream(targetPath);
      const throttleStream = new Throttle(SINGLE_CONNECTION_RATE);
      fileReadStream.pipe(throttleStream).pipe(res);
    
      // 异常处理别漏,文件不存在时直接返回404
      fileReadStream.on('error', () => {
        res.sendStatus(404);
      })
    })
    
    如果要控制服务端总出口带宽,维护一个全局共享的令牌池即可,所有下载连接共同消耗总令牌额度,避免多连接打满服务器带宽。
  • 反向代理层层限速
    最推荐的方案,把下载请求转发给Nginx/Caddy这类反向代理处理,直接通过配置实现单连接限速、全局带宽阈值控制、连接数限制,不需要写业务代码,性能比Node层实现高一个量级。比如Nginx只需要加两行配置就能实现单连接下载到1MB后限速到200KB/s:
    limit_rate_after 1m;
    limit_rate 200k;
    

下载速度提升实现

  • 剥离Node进程的文件传输职责
    不要让Node业务进程直接处理文件流传输,Node单线程事件循环模型扛大文件传输时会抢占正常接口的计算资源,传输效率也很低。最优方案是Node只做下载权限校验,校验通过后返回内部跳转头让反向代理接管文件传输:Nginx对应的是X-Accel-Redirect头,Caddy也有对应的内部跳转配置,反向代理会用sendfile零拷贝机制传输文件,比Node层res.download()的传输效率高5~10倍。
  • 支持断点续传与多线程下载
    默认res.download()不支持HTTP Range请求,大文件下载时一旦网络中断就得从头开始,也不支持客户端多线程分块拉取。要么手动处理请求里的Range头,返回206分块响应;要么直接交给反向代理托管静态文件,默认就支持Range请求,大文件下载速度能提升2~5倍。
  • 按需开启传输压缩
    对文本、代码包这类可压缩率高的文件,在反向代理层开启gzip或brotli压缩,能减少30%~70%的实际传输数据量,间接提升下载速度。注意zip、mp4、图片这类已经压缩过的格式不要重复压缩,只会浪费CPU资源没有实际收益。
  • 合理配置缓存策略
    对不频繁更新的文件,设置Cache-Control、ETag响应头,让客户端和CDN节点缓存文件内容,重复下载时直接从就近节点或本地缓存拉取,不需要回源到应用服务器。

注意:不管是限速还是提速需求,优先在反向代理/CDN层实现,不要在Node业务代码里堆逻辑。业务层只需要处理权限校验、文件路径映射这类业务逻辑,传输层的优化交给专门的组件做,稳定性和性能都比手写业务逻辑好很多。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:21:17