在橙星云的心理咨询业务系统中,咨询师经常需要将两小时以上、体积超过 1GB 的高清访谈录像上传到云端对象存储(OSS)。
如果仅仅使用普通的 <input type="file"> 搭配常规的 Axios POST 请求将整个文件上传,浏览器内存占用会显著升高,甚至导致标签页崩溃。此外,在网络不稳定的情况下,一旦上传过程发生中断,进度就会清零,用户只能重新上传。为了保障弱网环境下的上传可靠性,前端需要引入切片上传与断点续传机制。
Blob.slice() 实现文件切割
浏览器底层的 File 对象继承了 Blob 接口,这为我们提供了在前端进行字节级切割的能力。
“`javascript
// 设定切片大小:5MB
const CHUNK_SIZE = 5 1024 1024;
const chunks = [];
let currentByte = 0;
while (currentByte < file.size) {
const chunk = file.slice(currentByte, currentByte + CHUNK_SIZE);
chunks.push(chunk);
currentByte += CHUNK_SIZE;
}
“`
通过这几行代码,一个 1GB 的大文件可以被分割成大约 200 个 5MB 的小文件块。在此基础上,前端可以使用 Promise.all 控制并发数量(例如同时上传 3 个切片),从而更有效地利用上行带宽。
前端 Hash 计算与断点续传
切片解决了单次网络传输压力过大的问题,但还需要处理网络中断后的续传逻辑。
在上传前,前端可以利用 Web Worker 开启独立线程,对文件进行 MD5 Hash 计算,生成该文件的唯一标识。获取到 Hash 后,前端会向后端发送一个探测请求,查询该 Hash 对应的文件是否已经存在上传记录以及具体的切片接收情况。
后端通过数据库检索,如果发现该文件此前已经成功接收了前 149 个切片,会将这个状态返回给前端。前端收到响应后,会直接跳过已经上传的部分,从第 150 个切片继续发送。从用户的视角来看,上传进度条会自动恢复到中断前的位置并继续推进。
服务端切片合并
当所有切片都安全传输到服务器的临时目录后,前端会发起一个合并指令。后端接收到指令后,根据切片的索引顺序,利用文件流合并技术(如 Java 的 RandomAccessFile 或 Node.js 的 fs.createWriteStream)将这些小块重新组合成一个完整的高清视频文件。
对于包含大文件上传的 B 端业务场景而言,单纯依赖网络稳定性是不现实的。通过分片减小单次请求粒度,配合文件 Hash 探针实现断点续传机制,能够有效避免网络抖动带来的传输失败,提升系统的工程健壮性和用户上传体验。
