当前位置:首页 > JavaScript

js实现文件上传限速

2026-03-01 17:42:43JavaScript

文件上传限速实现方法

在JavaScript中实现文件上传限速可以通过控制上传数据块的速率来实现。以下是几种常见的方法:

使用XMLHttpRequest和定时器

通过分块上传文件并控制每个数据块的上传间隔来实现限速:

js实现文件上传限速

function uploadWithThrottle(file, url, maxSpeed) {
  const chunkSize = 1024 * 10; // 10KB
  const totalChunks = Math.ceil(file.size / chunkSize);
  let currentChunk = 0;
  const delay = (chunkSize / maxSpeed) * 1000; // 毫秒

  function uploadNextChunk() {
    if (currentChunk >= totalChunks) return;

    const start = currentChunk * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);

    const xhr = new XMLHttpRequest();
    xhr.open('POST', url, true);
    xhr.setRequestHeader('Content-Type', 'application/octet-stream');
    xhr.setRequestHeader('X-Chunk-Index', currentChunk);
    xhr.setRequestHeader('X-Total-Chunks', totalChunks);

    xhr.onload = function() {
      currentChunk++;
      setTimeout(uploadNextChunk, delay);
    };

    xhr.send(chunk);
  }

  uploadNextChunk();
}

使用Fetch API和AbortController

利用Fetch API和AbortController实现更精细的控制:

js实现文件上传限速

async function throttledUpload(file, url, maxSpeed) {
  const chunkSize = 1024 * 10; // 10KB
  const totalChunks = Math.ceil(file.size / chunkSize);
  const controller = new AbortController();

  for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);

    const startTime = Date.now();
    try {
      await fetch(url, {
        method: 'POST',
        body: chunk,
        headers: {
          'Content-Type': 'application/octet-stream',
          'X-Chunk-Index': i,
          'X-Total-Chunks': totalChunks
        },
        signal: controller.signal
      });

      const elapsed = Date.now() - startTime;
      const expectedTime = (chunkSize / maxSpeed) * 1000;
      if (elapsed < expectedTime) {
        await new Promise(resolve => 
          setTimeout(resolve, expectedTime - elapsed));
      }
    } catch (error) {
      if (error.name !== 'AbortError') throw error;
    }
  }
}

使用Web Worker进行后台限速

将上传逻辑放在Web Worker中以避免阻塞主线程:

// worker.js
self.onmessage = function(e) {
  const { file, url, maxSpeed } = e.data;
  const chunkSize = 1024 * 10;
  const totalChunks = Math.ceil(file.size / chunkSize);

  (async function() {
    for (let i = 0; i < totalChunks; i++) {
      const start = i * chunkSize;
      const end = Math.min(start + chunkSize, file.size);
      const chunk = file.slice(start, end);

      const startTime = Date.now();
      try {
        await fetch(url, {
          method: 'POST',
          body: chunk,
          headers: {
            'Content-Type': 'application/octet-stream',
            'X-Chunk-Index': i,
            'X-Total-Chunks': totalChunks
          }
        });

        const elapsed = Date.now() - startTime;
        const expectedTime = (chunkSize / maxSpeed) * 1000;
        if (elapsed < expectedTime) {
          await new Promise(resolve => 
            setTimeout(resolve, expectedTime - elapsed));
        }

        self.postMessage({
          progress: (i + 1) / totalChunks
        });
      } catch (error) {
        self.postMessage({ error: error.message });
        break;
      }
    }
  })();
};

计算上传速度的辅助函数

实现一个计算实时上传速度的函数:

function calculateSpeed(startTime, endTime, bytesSent) {
  const duration = (endTime - startTime) / 1000; // 转换为秒
  const speed = bytesSent / duration; // 字节/秒
  return {
    bytesPerSecond: speed,
    kilobytesPerSecond: speed / 1024,
    megabitsPerSecond: (speed * 8) / (1024 * 1024)
  };
}

注意事项

  1. 分块大小应根据实际需求调整,过小会增加请求次数,过大则限速效果不明显
  2. 服务器需要支持分块上传并能够重组文件
  3. 网络延迟会影响实际的上传速度,限速值应略低于目标值
  4. 对于大文件上传,应考虑加入暂停/恢复功能
  5. 浏览器兼容性问题需要考虑,特别是对于较旧的浏览器

以上方法可以根据具体需求进行组合和调整,以实现精确的文件上传限速控制。

标签: 文件上传js
分享给朋友:

相关文章

js实现vue

js实现vue

Vue.js 简介 Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。其核心库专注于视图层,易于与其他库或现有项目整合。 实现 Vue.js 的基本步骤 安装 Vue.j…

js实现拖拽

js实现拖拽

实现拖拽的基本步骤 通过监听鼠标事件(mousedown、mousemove、mouseup)实现拖拽功能。以下是核心代码逻辑: const draggableElement = document.…

js实现继承

js实现继承

原型链继承 通过将子类的原型指向父类的实例实现继承。子类实例可以访问父类原型上的属性和方法。 function Parent() { this.name = 'parent'; } Parent…

js实现日历

js实现日历

实现日历的基本思路 使用JavaScript实现日历的核心是动态生成日期表格,并处理月份切换逻辑。需要计算当前月的天数、起始星期几,并动态渲染到页面上。 获取当前日期信息 通过Date对象获取当前年…

js实现选项卡

js实现选项卡

实现选项卡的基本思路 选项卡通常由一组标签和对应的内容面板组成。点击标签时,显示对应的内容面板,隐藏其他面板。实现这一效果需要结合HTML结构、CSS样式和JavaScript交互逻辑。 HTML结…

js实现抽奖

js实现抽奖

实现抽奖功能的基本思路 抽奖功能的核心是随机选择奖项并展示结果。可以通过数组存储奖项,利用随机数生成索引,最后通过动画增强用户体验。 准备奖项数据 定义一个数组存储奖项信息,每个奖项可以包含名称、图…