前端大文件切片上传
更新时间:2023-02-22 15:57:53标签:web前端
浏览器端
文件切片和MD5值计算
1import SparkMD5 from 'spark-md5';2import { Observable } from 'rxjs';34export interface SlicedFile {5 md5: string;6 chunks: Blob[];7}89export function fileSlice(file: File, sliceSize: number/* byte */) {10 return new Observable<[number, SlicedFile | null]>(subscriber => {11 const spark = new SparkMD5.ArrayBuffer();12 const maxCount = Math.ceil(file.size / sliceSize);13 const chunks: Blob[] = [];14 const fileReader = new FileReader();15 fileReader.onload = (e) => {16 spark.append(e.target!.result as ArrayBuffer);17 loadNext();18 };19 fileReader.onerror = (err) => {20 subscriber.error(err);21 };22 const loadNext = () => {23 if (chunks.length < maxCount) {24 const start = chunks.length * sliceSize;25 subscriber.next([Math.min(1, start / file.size), null]);26 const end = Math.min(start + sliceSize, file.size);27 const blob = file.slice(start, end);28 fileReader.readAsArrayBuffer(blob);29 chunks.push(blob);30 } else {31 subscriber.next([1, { md5: spark.end(), chunks }]);32 subscriber.complete();33 }34 };35 loadNext();36 return {37 unsubscribe() {38 fileReader.abort();39 },40 };41 });42}
上传过程
1/**2 * @type {SlicedFile}3 */4var slicedFile;5(async () => {6 for (let i = 0; i < slicedFile.chunks.length; i += 1) {7 const formData = new FormData();8 formData.append('file', slicedFile.chunks[i]);9 await fetch(`/upload?md5=${slicedFile.md5}&index=${i}`, {10 body: formData11 });12 }13})();
暂停上传
前端中断顺序上传过程的行为即为暂停,上传进度为最后一次上传成功的切片
继续上传
- 服务端需要提供一个接口,接收参数为md5,前端通过此接口查询该md5对应的文件是否处于暂停中的状态;
- 如果查询到该md5对应的文件处于暂停状态,则返回前端当前暂停处于第几个切片;
- 前端从该切片开始,继续上传任务;
文件秒传
- 前端根据md5值,通过后端接口查询该md5值对应文件的存储状态;
- 如果查询到该文件已经存在于文件服务器,则直接展示文件链接(根据业务需求);
服务端
建立一个临时文件夹,名称为用户上传文件的md5
例如:
- 518798f72fea56abae47a08e0b363021(文件夹名,md5值)
- 0(第一个切片)
- 1(第二个切片)
- 2(第三个切片)
- 3(第四个切片)
- ...
用户暂停上传
- 保留该上传任务的临时文件夹及所有已完成上传的切片文件;
- 可以在数据库记录当前文件的上传状态(比如暂停中),uniqueID取md5;
用户继续上传
- 查询该md5对应的文件状态是否为暂停中;
- 继续接收用户上传的切片;
用户上传成功
- 所有切片完成上传后,合并所有切片,并校验md5值;
- 存储到服务器,并更新数据库状态;
文件秒传
- 数据库保存某个文件的md5及该文件的存储状态(比如上传成功);
- 提供md5查询接口,前端根据md5查询某个文件是否存在,若存在则返回文件链接(根据业务需求);