序言
文件上传是我们经常遇到的一个业务。一般就是用户点击上传,我们拿到 File 数据,再传给后端。但当文件体积过大,一次性上传可能会导致传输时间过长,且在网络不稳定的情况下容易失败,需要重新上传整个文件,这不仅浪费资源,还大大降低了用户体验。因此,分片上传技术应运而生,通过将大文件分割成多个小片(Part),每个小片可以独立地上传,并在服务器端重新组合成完整的文件。话不多说,我们进入正题。
分片
分片,顾名思义就是将文件进行拆分成多个块 chunk。分片规则可以根据业务所决定,以下我们假设,每个 chunk 的最大为 10M,那么分片的代码如下。
const chunkSize = 10 * 1024 * 1024;
const chunkCount = Math.ceil(file.size / chunkSize); // 总片数
for (let chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++) {
const start = chunkIndex * chunkSize;
const end = Math.min(file.size, start + chunkSize);
const chunk = file.slice(start, end);
// 此时 chunk 就是我们所分片出来的数据
}
上传
一般呢。我们拿到分片数据 chunk 后,就可以上传给后端。但后端还需要校验最后上传到后端的文件的完整性。一般是采用 md5 进行加密后验证。
import SparkMD5 from 'spark-md5';
function readAsArrayBuffer(blob: Blob) {
return new Promise<ArrayBuffer>((resolve, reject) => {
const reader = new FileReader();
reader.onload = function (event) {
resolve(event.target.result as ArrayBuffer);
};
reader.onerror = (error) => {
reject(error);
};
reader.readAsArrayBuffer(blob);
});
};
function fileSliceUpload() {
const chunkSize = 10 * 1024 * 1024;
const chunkCount = Math.ceil(file.size / chunkSize); // 总片数
const md5 = new SparkMD5.ArrayBuffer();
for (let chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++) {
const start = chunkIndex * chunkSize;
const end = Math.min(file.size, start + chunkSize);
const chunk = file.slice(start, end);
// 计算md5
const chunkBuffer = await readAsArrayBuffer(chunk);
md5.append(chunkBuffer);
// 此时 chunk 就是我们所分片出来的数据
// 进行 partUpload
}
// 上传完毕
// uploadComplete(md5.end());
// 校验上传文件的完整性
}
结尾
以上就是分片上传的大致思路啦。欢迎大家讨论交流