当前位置:首页 > JavaScript

js实现文件上传限速

2026-03-01 17:42:43JavaScript

文件上传限速实现方法

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

使用XMLHttpRequest和定时器

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

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实现更精细的控制:

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实现分页

js实现分页

实现分页的基本思路 分页功能通常需要处理数据分割、页码生成和用户交互。核心逻辑包括计算总页数、根据当前页截取数据、渲染页码按钮等。 前端分页实现(静态数据) 假设已有全部数据,仅需前端分页展示:…

vue.js实现轮播

vue.js实现轮播

Vue.js 实现轮播功能 使用第三方库(推荐) Vue.js 生态中有许多成熟的轮播组件库,例如 vue-awesome-swiper 或 swiper,它们功能丰富且易于集成。 安装 swipe…

js实现

js实现

实现 JavaScript 功能的方法 在 JavaScript 中实现特定功能通常涉及多个步骤。以下是常见的实现方法: 基础语法和变量声明 使用 let 或 const 声明变量: let…

js实现复制到剪贴板

js实现复制到剪贴板

使用document.execCommand方法(传统方式,已废弃但部分浏览器仍支持) 该方法适用于旧版浏览器,但已被标记为废弃。执行前需确保文本已被选中: function copyToClipb…

js实现论坛

js实现论坛

实现论坛的基本功能 使用JavaScript实现一个论坛需要结合前端和后端技术。前端可以使用React、Vue或Angular等框架,后端可以选择Node.js配合Express或Koa框架。数据库可…

jquery文件上传

jquery文件上传

jQuery 文件上传实现方法 基础文件上传实现 使用 jQuery 结合 HTML5 的 FormData 对象可以实现异步文件上传。创建一个包含文件输入的表单: <form id="upl…