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

如何在Electron应用中使用node-fetch限制下载速度?

如何在Electron应用中限制fetch下载的速度?

问题描述

我有一段用于Electron应用的文件下载逻辑,简化后如下:

import fetch from "node-fetch";
import path from "path";
import fs from "fs";

const filePath = "C:\\Downloads\\";

const fileName = path.basename(url);
const fullFilePath = path.join(filePath, fileName);

const response = await fetch(url, options);

const fileStream = fs.createWriteStream(fullFilePath);
response.body.pipe(fileStream);

response.body.on("data", (chunk: Buffer) => {
  // ... 跟踪进度
});

response.body.on("end", () => {
  fileStream.end();
  fileStream.close();
  // ... 上报完成事件
});

现在需要实现允许用户设置最大下载速度的功能,请问该怎么做?

解决方案

方法1:使用现成节流包(推荐)

可以用stream-throttle这个npm包,它专门适配Node.js Stream API来控制流速率,在Electron中可直接使用。

步骤:

  1. 安装依赖:
npm install stream-throttle
  1. 修改代码,在响应流和文件流之间插入节流层:
import fetch from "node-fetch";
import path from "path";
import fs from "fs";
import { Throttle } from "stream-throttle";

// 用户设置的最大速度,单位:字节/秒(例:1MB/s = 1024*1024)
const maxSpeed = 1024 * 1024; 

const filePath = "C:\\Downloads\\";
const fileName = path.basename(url);
const fullFilePath = path.join(filePath, fileName);

const response = await fetch(url, options);

// 创建节流流并设定速率
const throttleStream = new Throttle({ rate: maxSpeed });

const fileStream = fs.createWriteStream(fullFilePath);
// 先经过节流流再写入文件
response.body.pipe(throttleStream).pipe(fileStream);

// 进度跟踪与结束事件逻辑保持不变
response.body.on("data", (chunk: Buffer) => {
  // ... 跟踪进度
});

response.body.on("end", () => {
  fileStream.end();
  fileStream.close();
  // ... 上报完成事件
});

用户调整maxSpeed的值即可修改最大下载速度,逻辑简单且稳定。

方法2:自定义节流Transform流

如果不想依赖第三方包,可手动实现Transform流,通过计算数据块传输延迟来控制速率。

示例代码:

import fetch from "node-fetch";
import path from "path";
import fs from "fs";
import { Transform } from "stream";

class SpeedThrottle extends Transform {
  constructor(options) {
    super(options);
    this.maxSpeed = options.maxSpeed; // 字节/秒
    this.bytesSent = 0;
    this.startTime = Date.now();
  }

  _transform(chunk, encoding, callback) {
    const now = Date.now();
    const elapsed = (now - this.startTime) / 1000; // 已流逝时间(秒)
    const expectedBytes = this.maxSpeed * elapsed; // 理论应传输字节数
    // 计算需要延迟的时间,确保总速率不超限
    const delay = (this.bytesSent + chunk.length - expectedBytes) / this.maxSpeed * 1000;

    if (delay > 0) {
      setTimeout(() => {
        this.push(chunk);
        this.bytesSent += chunk.length;
        callback();
      }, delay);
    } else {
      this.push(chunk);
      this.bytesSent += chunk.length;
      callback();
    }
  }
}

// 用户设置的最大速度
const maxSpeed = 1024 * 1024; 

const filePath = "C:\\Downloads\\";
const fileName = path.basename(url);
const fullFilePath = path.join(filePath, fileName);

const response = await fetch(url, options);

const throttleStream = new SpeedThrottle({ maxSpeed });
const fileStream = fs.createWriteStream(fullFilePath);

response.body.pipe(throttleStream).pipe(fileStream);

// 后续逻辑保持不变
response.body.on("data", (chunk: Buffer) => {
  // ... 跟踪进度
});

response.body.on("end", () => {
  fileStream.end();
  fileStream.close();
  // ... 上报完成事件
});

这个自定义流会动态计算每个数据块的传输延迟,确保整体速率不超过设定值。

注意事项

  • 速率单位是字节/秒,如果用户界面用MB/s显示,需做单位转换(1MB = 1024*1024字节)。
  • 两种方法均可在Electron主进程、开启nodeIntegration的渲染进程中使用。
  • 若需动态调整速度,可给节流流添加方法修改maxSpeed属性(比如自定义流中加setSpeed(newSpeed))。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:32:37