前端上传切片优化以及实现

你说的 前端上传切片优化以及实现,主要涉及到大文件分片上传(chunk upload)、并发控制、断点续传、秒传、重试机制等。下面我给你梳理一下实现思路和优化点。


🔹 场景与痛点

  • 大文件上传(>100MB):直接上传会超时或失败。
  • 网络不稳定:中断后需重传。
  • 上传速度慢:需要并发分片上传。
  • 服务端压力大:需要合理控制并发与分片大小。

🔹 基础实现流程

  1. 文件切片

    使用 Blob.slice 方法将文件分割为固定大小的分片(比如 2MB/5MB)。

    ini 复制代码
    function createFileChunks(file: File, chunkSize = 2 * 1024 * 1024) {
      const chunks: Blob[] = [];
      let cur = 0;
      while (cur < file.size) {
        chunks.push(file.slice(cur, cur + chunkSize));
        cur += chunkSize;
      }
      return chunks;
    }
  2. 计算文件唯一标识(hash)

    通常用 MD5/SHA1 或者基于文件名 + 大小 + 上次修改时间。

    可以在浏览器端用 spark-md5:

    javascript 复制代码
    import SparkMD5 from "spark-md5";
    
    async function calculateHash(chunks: Blob[]) {
      const spark = new SparkMD5.ArrayBuffer();
      for (const chunk of chunks) {
        const buffer = await chunk.arrayBuffer();
        spark.append(buffer);
      }
      return spark.end(); // 文件hash
    }
  3. 上传分片

    每个分片通过 FormData 上传:

    php 复制代码
    async function uploadChunk(chunk: Blob, index: number, fileHash: string) {
      const formData = new FormData();
      formData.append("chunk", chunk);
      formData.append("index", String(index));
      formData.append("fileHash", fileHash);
    
      return fetch("/upload", {
        method: "POST",
        body: formData,
      });
    }
  4. 合并文件

    前端所有分片上传完成后,调用后端 /merge 接口,通知服务端进行文件合并。


🔹 优化点

  1. 并发控制

    使用 Promise.all 并发上传,但需要限制最大并发数:

    ini 复制代码
    async function limitUpload(chunks, limit = 5) {
      const pool: Promise<any>[] = [];
      let i = 0;
    
      async function run() {
        if (i >= chunks.length) return;
        const task = uploadChunk(chunks[i], i, "fileHash").then(run);
        pool.push(task);
        i++;
      }
    
      const workers = Array(limit).fill(null).map(run);
      await Promise.all(workers);
    }
  2. 断点续传

    • 上传前向服务端查询已上传的分片列表。
    • 跳过已完成的分片,仅上传剩余分片。
  3. 秒传

    • 上传前计算 hash。
    • 询问服务端该文件是否已存在,存在则直接返回成功。
  4. 失败重试

    • 针对失败的分片,做 最多 N 次重试。
    javascript 复制代码
    async function retry(fn, retries = 3) {
      while (retries--) {
        try {
          return await fn();
        } catch (e) {
          if (!retries) throw e;
        }
      }
    }
  5. 上传进度显示

    • 每个分片上传时用 XMLHttpRequest.onprogress 或 fetch + ReadableStream 计算进度。
    • 进度 = 已上传分片大小 / 总文件大小。

🔹 前端完整流程

  1. 选择文件 → 切片 → 计算 hash。
  2. 调用 /checkFile → 返回已上传分片。
  3. 跳过已完成分片,继续上传剩余分片(带并发控制 & 重试机制)。
  4. 上传完后请求 /merge。
  5. 前端实时展示进度条。

🔹 技术选型

  • 切片与上传 :原生 Blob.slice + fetch/axios。
  • hash计算 :spark-md5(大文件可用 Web Worker 避免卡 UI)。
  • 断点续传:前端记录进度 / 服务端存储分片状态。
  • 进度显示 :XMLHttpRequest.onprogress 或 axios.onUploadProgress。

相关推荐
泡海椒1 小时前
趋势分析报表:jquick-pdf折线图PDF生成实战
java·大数据·运维·服务器·前端·pdf
默_笙1 小时前
🚙 一条腿走路会摔:ES 关键词检索、混合召回与 ReRank 裁判
前端·javascript
YIAN1 小时前
从跨域代理到 WebSocket:梳理前端实时通信的底层逻辑与完整实践
前端·websocket
一曲终散1 小时前
创建 SVG 图标预览页面:从零实现到解决 CORS 问题
前端
静默回滚1 小时前
iPhone照片电脑上打不开:HEIC解码从原理到WASM
前端
dsyyyyy11012 小时前
Vue 3 Watch 监视完全指南
前端·javascript·vue.js
航飞光电市场经理2 小时前
人员定位系统“全栈自研”技术解析:从射频前端到定位引擎的架构拆解
前端·架构
Apifox2 小时前
Apifox 9 月更新|CLI 能力升级、GitLab 私有化部署接入与产品体验优化
前端·后端·测试
deli0072 小时前
随机乱跳为什么能画出完美三角形:混沌游戏分形实验室
前端
Gizzap_Tech2 小时前
国内官网增加英文版:URL、语言切换与 hreflang 怎么配置?
前端