大文件上传解决方案
一、业务场景:
ai课堂需求,涉及到视频的播放,需要在后台上传视频,视频的最大限制是500MB,当视频较大的时候,普通的上传会有问题,导致上传失败。这就要求我们将大文件进行拆分,分片进行上传,在所有分片上传成功之后,再进行合并。
二、前后端交互流程:
1、前端调用后端分片文件上传初始化接口
2、在初始化接口调用后,后端给前端返回分片上传的地址,分片数量是几个,后端就会给前端返回几个地址。前端去调用这些地址(前端直连minio),进行分片上传。
3、待所有分片都上传完毕后,调用合并接口进行文件的合并。
最终得到完整的视频播放地址。
三、核心代码
/分片上传axiosPartUpload(file) {//分片大小const chunkSize = 10 * 1024 * 1024;const fileSize = file.size//计算当前选择文件需要的分片数量const chunkCount = Math.ceil(fileSize / chunkSize)this.totalCount=chunkCount;let initParams={fileName:file.name,fileSize:fileSize,partCount:chunkCount,contentType:file.type}this.isUploading=true;//调用初始化接口initUpload(initParams).then(async res=>{console.log(res,'初始化接口返回结果')this.uploadId=res.uploadId;this.objectName=res.objectName;let urlList=res.urlList;for(let i=0;i<urlList.length;i++){//文件截取let start = i * chunkSize;let end = Math.min(fileSize, start + chunkSize);let chunkFile = file.slice(start, end);//调用分片上传接口await uploadPart(urlList[i],chunkFile).then(res2=>{ console.log(`第${i+1}个分片上传成功`)this.successCount=i+1;}).catch(err=>{this.isUploading=false;this.$message.error(`第${i+1}个分片上传失败`)})}//所有分片上传完成之后,进行合并let mergeParams={uploadId:this.uploadId,objectName:this.objectName}mergeFile(mergeParams).then(res2=>{console.log(res2,'合并接口返回结果')this.$emit("getVideoUrl", res2.fileUrl, file.name);this.$message({message: "上传成功",type: "success"});this.isUploading=false;})}).catch(err=>{this.isUploading=false;this.$message({message: "上传失败,请重新选择文件上传!",type: "error"})})},
四、存在问题
1、缺少断点续传逻辑。
2、分片串行上传,上一分片上传结束后上传下一分片,效率不高。