本内容首发于工粽号:程序员大澈,每日分享一段优质代码片段,欢迎关注和投稿!
大家好,我是大澈!
本文约 1100+ 字,整篇阅读约需 2 分钟。
大文件切片上传,我一般会分为4步来搞:文件切片-计算哈希值-上传管理-上传完成合并验证。其中,上传管理又可以包括:切片上传验证、上传进度记录、断点续传。
今天分享一段优质 JS 代码片段,就是关于大文件切片上传的第3部分,上传管理的简单实现。
老规矩,先阅读代码片段并思考,再看代码解析再思考,最后评论区留下你的见解!
async function uploadFile(file, url) {const chunkSize = 10 * 1024 * 1024; // 10 MBconst chunks = fileToChunks(file, chunkSize);const chunkHashes = await getChunksHashes(chunks);const uploadedChunks = new Set(JSON.parse(localStorage.getItem(file.name)) || []);for (let i = 0; i < chunks.length; i++) {if (uploadedChunks.has(i)) {console.log(`Chunk ${i} already uploaded`);continue;}const formData = new FormData();formData.append('chunk', chunks[i]);formData.append('hash', chunkHashes[i]);formData.append('index', i);formData.append('filename', file.name);const response = await fetch(url, {method: 'POST',body: formData,});if (response.ok) {uploadedChunks.add(i);localStorage.setItem(file.name, JSON.stringify([...uploadedChunks]));} else {throw new Error(`Failed to upload chunk ${i}`);}}console.log('All chunks uploaded successfully');
}async function getChunksHashes(chunks) {const spark = new SparkMD5.ArrayBuffer();const hashes = [];for (const chunk of chunks) {const hash = await new Promise((resolve) => {const reader = new FileReader();reader.onload = (event) => {spark.append(event.target.result);resolve(spark.end());};reader.readAsArrayBuffer(chunk);});hashes.push(hash);}return hashes;
}
分享原因
这段代码展示了如何在浏览器中实现文件分片上传和断点续传的功能。
通过将文件分成多个小片段逐个上传,同时利用本地存储记录上传进度,以确保在网络中断或其他原因导致上传失败的情况下,可以继续上传未完成的部分。
代码解析
1. uploadFile 函数
这个函数的目的是:将文件分片并逐片上传,同时记录上传进度以便于断点续传。
chunkSize:定义每个分片的大小,这里是10MB。
chunks:将文件分成多个分片。
chunkHashes:计算每个分片的哈希值,用于校验分片完整性。
uploadedChunks:从本地存储中读取已上传的分片索引,避免重复上传。
遍历分片,检查当前分片是否已经上传,若已上传则跳过。
创建 FormData 对象并添加分片数据、哈希值、索引和文件名,使用 fetch 将分片上传至服务器。
若上传成功,将当前分片索引记录到 uploadedChunks 中并存储到本地存储。
2. getChunksHashes 函数
这个函数的目的是:定义计算文件各个分片的哈希值,以确保上传过程中数据的完整性。
创建 SparkMD5.ArrayBuffer 实例,用于生成 MD5 哈希。
遍历分片,使用 FileReader 读取每个分片的内容并计算其哈希值。
将每个分片的哈希值存储在 hashes 数组中。
- end -