前端大文件传不动?分片+断点续传实战方案
有没有试过上传一个10G的视频文件,结果浏览器卡成PPT?
大文件上传这事儿,说简单也简单,说难能把人整崩溃。去年我们团队传设计院的BIM模型,3个G的文件传了8次才成功,那真是血压飙升的8次重试啊!不过现在摸出门道了,用对方法连10G文件都能丝滑上传,今天就把这些血泪教训变成你的通关秘籍。
🔪第一招:庖丁解牛式分片切割
搞大文件上传就像搬大象,整只扛不动就切片嘛!这里有个黄金法则——1-5MB的分片大小最合适。别贪心切太大,不然网络波动就白传;也别切太碎,服务器处理起来会骂街。
手把手切片教学:
- 掏出你的
Blob.slice()
这把手术刀 - 按公式
分片数=文件大小/分片尺寸
计算 - 把切好的肉片(分片)装进数组待命
举个栗子,传个500MB的视频:
javascript复制const CHUNK_SIZE = 5 * 1024 * 1024; //5MB黄金分割const chunks = [];let current = 0;while (current < file.size) {chunks.push(file.slice(current, current + CHUNK_SIZE));current += CHUNK_SIZE;}
分片尺寸对比表
分片大小 | 上传速度 | 失败重传成本 | 适用场景 |
---|---|---|---|
1MB | ⚡⚡⚡ | 极低 | 4G网络 |
5MB | ⚡⚡ | 较低 | WiFi环境 |
10MB | ⚡ | 较高 | 局域网 |
🔄第二招:断点续传保命符
传大文件最怕啥?传了90%突然断网!这时候就需要断点续传来救场。原理跟打游戏存档一样,记住传到哪里了下次接着传。
三步搭建存档点:
- 给每个分片办身份证(MD5哈希值)
- 已传分片名单存localStorage或服务器
- 重新上传时跳过"已通关"分片
关键代码片段:
javascript复制// 生成文件指纹const spark = new SparkMD5.ArrayBuffer();const reader = new FileReader();reader.onload = e => {spark.append(e.target.result);const hash = spark.end(); //这就是文件身份证};reader.readAsArrayBuffer(file);
🚀第三招:多线程飙车技术
浏览器主线程就像单车道,用Web Workers开个应急车道,把哈希计算这种重活扔到后台,页面照样流畅刷微博。
性能对比实验:
处理方式 | 10G文件计算时间 | 页面卡顿感 |
---|---|---|
主线程计算 | 58秒 | 完全冻住 |
Web Workers | 62秒 | 毫无感觉 |
虽然多花了4秒,但用户体验天上地下!设置worker很简单:
javascript复制// 主线程const worker = new Worker('hash.js');worker.postMessage({ chunks });worker.onmessage = e => console.log(e.data.hash);// worker线程self.importScripts('spark-md5.js'); //加载工具库
📊第四招:进度条心理按摩术
人等进度条就像等外卖,实时反馈太重要了!用XMLHttpRequest的progress事件,每传完一片就更新进度。
防焦虑设计要点:
- 进度数值要真实(别搞假进度)
- 预估剩余时间(参考下载速度)
- 失败分片用红色标注
- 完成时放个烟花动画(用户需要仪式感)
javascript复制xhr.upload.onprogress = e => {const percent = (e.loaded / e.total) * 100;progressBar.style.width = percent + '%';};
💡小编私房技巧
- 冷知识:Chrome同时最多允许6个HTTP请求,想提速就控制在5个并发上传
- 血泪教训:千万别用文件名当哈希!用户改个名字就全乱套,得用文件内容生成指纹
- 秘传参数:上传头里加个
Content-Range: bytes 0-1023999/20480000
,服务器就知道你在玩分片 - 防呆设计:上传按钮点完后变成不可点状态,防手贱党连环点击
最近发现个神器——resumable.js,人家把分片、续传、重试都封装好了,比自己造轮子省心多了。不过建议新手先手动实现几次,彻底搞懂原理再用框架,别当调包侠哦!
最后说个真事:上周测试10G文件上传,用这套方案最高飙到50MB/s,传完文件比下楼取外卖还快。你看,找对方法,大文件也能变顺丰快递!