大文件上传
本文最后更新于 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
来处理!