网站首页 > 技术文章 正文
你说的 前端上传切片优化以及实现,主要涉及到大文件分片上传(chunk upload)、并发控制、断点续传、秒传、重试机制等。下面我给你梳理一下实现思路和优化点。
场景与痛点
- 大文件上传(>100MB):直接上传会超时或失败。
- 网络不稳定:中断后需重传。
- 上传速度慢:需要并发分片上传。
- 服务端压力大:需要合理控制并发与分片大小。
基础实现流程
- 文件切片
使用 Blob.slice 方法将文件分割为固定大小的分片(比如 2MB/5MB)。 - 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; }
- 计算文件唯一标识(hash)
通常用 MD5/SHA1 或者基于文件名 + 大小 + 上次修改时间。
可以在浏览器端用 spark-md5: - 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 }
- 上传分片
每个分片通过 FormData 上传: - 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, }); }
- 合并文件
前端所有分片上传完成后,调用后端 /merge 接口,通知服务端进行文件合并。
优化点
- 并发控制
使用 Promise.all 并发上传,但需要限制最大并发数: - 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); }
- 断点续传
- 上传前向服务端查询已上传的分片列表。
- 跳过已完成的分片,仅上传剩余分片。
- 秒传
- 上传前计算 hash。
- 询问服务端该文件是否已存在,存在则直接返回成功。
- 失败重试
- 针对失败的分片,做 最多 N 次重试。
- async function retry(fn, retries = 3) { while (retries--) { try { return await fn(); } catch (e) { if (!retries) throw e; } } }
- 上传进度显示
- 每个分片上传时用 XMLHttpRequest.onprogress 或 fetch + ReadableStream 计算进度。
- 进度 = 已上传分片大小 / 总文件大小。
前端完整流程
- 选择文件 → 切片 → 计算 hash。
- 调用 /checkFile → 返回已上传分片。
- 跳过已完成分片,继续上传剩余分片(带并发控制 & 重试机制)。
- 上传完后请求 /merge。
- 前端实时展示进度条。
技术选型
- 切片与上传:原生 Blob.slice + fetch/axios。
- hash计算:spark-md5(大文件可用 Web Worker 避免卡 UI)。
- 断点续传:前端记录进度 / 服务端存储分片状态。
- 进度显示:XMLHttpRequest.onprogress 或 axios.onUploadProgress。
猜你喜欢
- 2025-09-14 黑客通过钓鱼攻击劫持npm软件包:含chalk、debug等十余个高频库
- 2025-09-14 记录一次网盘资源不给提取码的经历!另类编程思维,Python破之!
- 2025-09-14 前端必读:如何在 JavaScript 中使用SpreadJS导入和导出 Excel 文件
- 2025-09-14 面试官:说说你对options请求的理解
- 2025-09-14 手把手教你写一个简易的微前端框架
- 2025-09-14 腾讯工程师案例实战:大型前端项目的断点调试共享化和复用化实践
- 2025-09-14 js 通过流的方式进行下载_js 下载流文件
- 2025-09-14 如何在关闭浏览器标签前,可靠地发送 HTTP 请求?
- 2025-07-09 跨域资源的共享(CORS)N种用法(跨域资源共享的缩写是?)
- 2025-07-09 Axios CORS 问题处理(axios has been blocked by cors policy)
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)