断点续传-vue

实现断点续传主题思路:
对文件进行每200MB切片,基于spark-md5计算出第一个切片文件的hash值,将文件的名称,大小,hash值传给后台,后台确认当前文件是否上传过,已上传过返回之前上传大小或第几个切片,前端再次上传切片,直到上传完成.

代码:

<el-upload
  class="upload-demo"
  ref='upload'
  action=""
  :http-request='calcMd5'
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :before-remove="beforeRemove"
  :limit="1"
  :on-exceed="handleExceed"
  :file-list="fileList">
  <el-button size="small" type="primary">点击上传</el-button>
</el-upload>
<script>
  export default {
    data() {
      return {
        fileList: [],
        chunkSize :1024*1024*200,//200MB
        source:null,
        uploadFileData:{
          download_chunk:0,//将上传第几个切片 0 为第一个
          md5:',
          file:null,
        },
      };
    },
    methods: {
      calcMd5(myFile){
        let blobSlice =
        File.prototype.slice ||
        File.prototype.mozSlice ||
        File.prototype.webkitSlice,
        file = myFile.file,
        chunkSize = this.chunkSize, // Read in chunks of 2MB
        chunks = Math.ceil(file.size / chunkSize),
        currentChunk = 0,
        spark = new SparkMD5.ArrayBuffer(),
        that=this,
        fileReader = new FileReader();
    fileReader.onload = function (e) {
        console.log("read chunk nr", currentChunk + 1, "of", chunks);
        spark.append(e.target.result); // Append array buffer
        currentChunk++;
        //文件太大  计算整个文件耗时太久 so  只计算第一个切片的hash
        if (currentChunk >= 1) {
            let md5=  spark.end();
            that.uploadFileData.file=file;
            that.uploadFileData.md5=md5;
            that.searchFile();
            console.log("finished loading");
            console.info("computed hash", spark.end()); // Compute hash
        } else {
            loadNext();
        }
        fileReader.onerror = function () {
           console.warn("oops, something went wrong.");
        };

         function loadNext() {
            var start = currentChunk * chunkSize,
            end = start + chunkSize >= file.size ? file.size : start + chunkSize;
            fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
        }

         loadNext();
      },
      async searchFile(){
         let obj={
            md5: this.uploadFileData.md5,
            size: this.uploadFileData.file.size,
            name:this.uploadFileData.file.name,
         }
         let {data:res}=await this.$axios.post('rul',obj);
         if(res.code!==0){
            this.$message.error(res.msg);
            return;
         }
         if(res.data.completed){ //判断是否已上传
            if(this.$refs.upload){
               this.$refs.upload.clearFiles(); //已上传清理文件
            }
            this.$message.success('已上传!');
            return;
         }
         //后台返回下一个上传下标  或者返回大小前端计算
         this.uploadFileData.download_chunk=res.data.download_chunk;
         //继续上传
         this.chunsFile();
      },
      async chunsFile(){
         this.source=this.$axios.CancelToken.source();//可用于取消正在上传的接口
         let config={
             cancelToken:this.source.token,
             headers:{
                "Content-Type":"multipart/form-data"
             },
         }
         let chunkLength=0;//文件切片后的长度
         //获取分片后的长度
         if (this.uploadFileData.file.size > this.chunkSize) {
            chunkLength = Math.ceil(this.uploadFileData.file.size / this.chunkSize);
         } else {
            chunkLength = 1
         }

        //用formData通过ajax2上传文件内容
        let fm = new FormData();
        fm.append('md5', this.uploadFileData.md5);//spark-md5计算出来的md5值
        fm.append('size',this.uploadFileData.file.size);
        fm.append('download_chunk',this.uploadFileData.download_chunk);
        fm.append('name ', this.uploadFileData.file.name);
        fm.append('file', this.uploadFileData.file.slice(this.uploadFileData.download_chunk *this.chunkSize, (this.uploadFileData.download_chunk + 1) * this.chunkSize);
        
        let {data:res}=await this.$axios.post('url',fm,config);
        if(res.code!==0){
            this.$message.error(res.msg);
            return;
         }
         if(res.data.completed){ //判断是否已上传
            if(this.$refs.upload){
               this.$refs.upload.clearFiles(); //已上传清理文件
            }
            this.$message.success(res.msg);
         }else{
            this.uploadFileData.download_chunk=res.data.download_chunk;
            this.chunsFile();  //继续上传下个切片
         }
        
      },
           
      handleRemove(file, fileList) {
        console.log(file, fileList);
      },
      handlePreview(file) {
        console.log(file);
      },
      handleExceed(files, fileList) {
        this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了       ${files.length + fileList.length} 个文件`);
      },
      beforeRemove(file, fileList) {
        return this.$confirm(`确定移除 ${ file.name }?`);
      }
    }
  }
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值