大文件上传
本文最后更新于 2024-09-30,文章内容可能已经过时。
大文件上传,通常使用文件分片形式进行文件上传,在获取到File时,我们可以使用内置的api slice()方法来进行文件分片,这个方法有两个参数,一个是起始位置到分片结束为止,File.slice(0, 1000)意思是从0开始截取到1000个文件字节内容,最终返回一个blob对象{ size: 1048576, type: "" }!
blob对象 和 FiLe对象一样通过body形式发送给服务端进行存储,不过通过slice分片方回的结果只是文件的基本信息(文件大小 文件类型 文件名...)真正的内容还需要通过FileReader对象才能读取到文件内容!
定义input file
<!-- 文件上传 -->
<div class="upload-file">
<input type="file" @change="handleFileChange" />
</div>监听 file 变化
async handleFileChange( e ){
console.log( '选择的文件:', e.target.files[0] );
console.time();
let result = await cutFile(e.target.files[0])
console.timeEnd();
console.log( '切割后的文件:', result );
}上面通过
input[type="file"]来获取文件File!并且通过
onchange来监听获取文件的变化!
cutFile函数来帮我们完成分片结果的处理!
创建cutFile分片函数
分片函数参数,文件对象 file, 需要分片大小[比如一个文件总大小为100M ,分成5M进行存储]
chunkCount 分片大小(一共多少个分片): 文件大小 / 分片大小
/*
* 将文件分片处理
* @param file 文件对象
* @param chunkSize 分片大小,默认 1M
* @returns {Array} 文件分片数组
*/
export const cutFile = async (file, chunkSize = 1024 * 1024) => {
// 分片大小
const chunkCount = Math.ceil(file.size / chunkSize);
const chunks = [];
for (let i = 0; i < chunkCount; i++) {
const result = await createChunks(file, i, chunkSize);
chunks.push(result);
}
return chunks;
};
createChunks函数,用来创建分片!
参数:文件当前索引分片大小 5M
/*
创建分片返回分片结果
*/
export const createChunks = (file, index, chunkSize) => {
return new Promise((resolve, reject) => {
// 开始分片索引
const start = index * chunkSize;
// 结束分片索引
const end = start + chunkSize;
const spark = new SparkMD5.ArrayBuffer();
const reader = new FileReader();
const blob = file.slice(start, end);
reader.onload = (e) => {
spark.append(e.target.result);
resolve({
start,
end,
index,
hash: spark.end(),
blob,
});
};
reader.readAsArrayBuffer(blob);
});
};
注意:这里我们用到了SparkMD5第三方库,用来帮助我们获取文件的hash值
hash值有助于给分片文件分配唯一值,当页面刷新或网络中断时,通过此hash标识请求后端,返回中断前的上传结果,并继续上传!
注意:计算hash值比较耗费时间 消耗内存,处理此问题,需要通过多线程方式 Worker来处理!