所谓断点续传,前提是上传文件为大文件,如果文件较小,则体现不出断点续传的优势。
断点续传大文件的优势:
1、文件上传过程中上传了一半,网络中断,再次上传可以从上次中断处开始上传,节省带宽和上传时间。
2、由于断点续传需要验证文件的hash,可以避免相同文件多次上传,节约服务器存储空间,节约用户操作时间,加上友好提示,可以提高用户的体验度。
断点续传的实现过程:
1、java服务器端我们只做简单介绍,需要实现一个两个接口,一个用来查询对应hash的文件是否已经上传,如果上传,上传了多少,是否完成。另一个接口用来保存上传的内容到文件里面,如果是新文件,则建立文件保存,如果是以及上传了一部分的文件,则从数据库查询出对应文件所在位置,追加写入新上传的数据。
2、前端需要一个input file输入框,用户选择文件后,计算文件的hash值,计算方式可以参考spark-md5计算文件hash值一文来实现。
之后请求发送hash值到查询文件状态接口获取文件上传的状态
let searchFile={ md5:fileMd5//spark-md5计算出的hash值 name:file.name//所上传文件名称 }; this.$axios.post("/checkFile",this.searchFile).then(res=>{ let { data }=res; if(data.state==0){//判断之前是否上传成功此文件 0未上传 chunksFile();//上传文件 }else if(data.state==1){ uploadFile.chunk=parseInt(data.maxChuck)+1;//将查询到的结果赋值给表单中的分片 chunksFile(); }else if(data.state==2){ this.$message({ duration:1500, type:"warning", message:"此视频已经上传过了" }); } }).catch((error)=>{ this.$message({ duration:1500, type:"error", message:"网络异常,请稍后再试" }); });
查询出文件的上传状态后,根据不同状态调用chunksFile()方法进行文件的上传。
let uploadFile={ chunk:0, isLastChunk:false//是否最后一片文件 fileName:filename//文件名称 }; //分片上传大文件的方法 function chunksFile(){ let file=this.$refs.batchfile.files[0],//需要上传的文件 chunkLength=0;//文件分片后的长度 this.uploadFile.fileName=file.name; //获取分片后的长度 if(file.size>1024*1024*10){ //每片长度10MB. chunkLength=Math.ceil(file.size/(1024*1024*10)); }else{ chunkLength=1 } //判断是不是最后一片,通知后台 uploadFile.chunk===chunkLength?uploadFile.isLastChunk=true:false; //用formData通过ajax2上传文件内容 let fm = new FormData(); fm.append('fileMd5',fileMd5);//spark-md5计算出来的md5值 fm.append('chunk',uploadFile.chunk); fm.append('isLastChunk ',uploadFile.isLastChunk ); fm.append('fileName ',uploadFile.fileName ); fm.append('theFile',file.slice(uploadFile.chunk*1024 * 1024 * 10, (uploadFile.chunk+1)*1024 * 1024 * 10) ); //通过ajax上传分片文件内容 this.$axios({ method: "post", url: "/uploadChuncks", data:fm }).then((res) => { let {data} = res; if(data.error==0){ //上传成功,分片加一,上传下一片文件 uploadFile.chunk=parseInt(data.chunck)+1; //上传完最后一片后传输结束 if(this.uploadFile.isLastChunk){ this.$message({duration:1500, type:"success", message:"上传视频成功" }); }else{ //递归调用上传下一片 chunksFile(); } }else{ this.$message({duration:1500, type:"error", message:data.message||"未知错误" }); } }).catch((error)=>{ this.$message({ duration:1500, type:"error", message:"网络异常,请稍后再试" }); }); }
这样将文件分片上传,从中断的分片处继续上传剩余的文件就可以实现断点续传的功能了。chunkFile本身实现的就是大文件的分片上传文件,单独出来不依赖spark-md5的hash值比对文件时,就是一个大文件上传功能。
本例中我们分的片是10mb一片,实际项目中分片的大小可以根据实际应用场景和实际网络状况进行调整。
由于web是在沙箱中运行,不能访问浏览器本地文件,所以web端的断点续传是不能实现像迅雷等下载软件类似的功能,保存上传和下载列表的,只能通过用户的二次点击来实现断点续传的功能。