当前位置:首页 > 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实现轮播

js实现轮播

实现基础轮播效果 使用HTML结构创建轮播容器和图片元素: <div class="carousel"> <div class="carousel-inner">…

js实现全选

js实现全选

实现全选功能的方法 在JavaScript中实现全选功能通常涉及监听全选复选框的点击事件,并根据其状态控制其他复选框的选中状态。以下是几种常见的实现方式: 基础DOM操作实现 通过获取所有目标复选框…

js实现选题

js实现选题

实现选题功能的JavaScript方法 基础实现方案 使用数组存储选项,通过随机索引选取: const options = ['选项A', '选项B', '选项C', '选项D']; const r…

vue实现文件上传

vue实现文件上传

文件上传的基本实现 在Vue中实现文件上传通常需要结合HTML的<input type="file">元素和JavaScript的File对象处理。创建一个基本的文件上传组件: <…

js实现密码

js实现密码

密码强度验证 使用正则表达式验证密码强度是一种常见方法。以下代码检查密码是否包含大小写字母、数字和特殊字符,且长度至少为8位: function checkPasswordStrength(pass…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: fun…