实现前端断点续传功能

实现原理将文件切割成几份,一份份的上传,上传完毕,再通过接口告知后端将所有片段合并

// 模板

<el-form-item label="请选择文件:" v-if="!processPercentage">
        <div class="upload-button-box">
          <input
            type="file"
            name="file" 
            ref="input"
            accept=".tar.gz"
            @change="onChange"
            class="upload-button"
          />
          <el-button size="small" type="primary">上传文件</el-button>
          <span v-if="form.file" style="margin-left: 15px">{{ this.form.file.name }}</span>
          <div class="tips">支持扩展名:.tar.gz</div>
        </div>
      </el-form-item>

// 引入依赖

import md5Hex from 'md5-hex'

// 定义数据

data () {
    return {
      form: {
        file: undefined
      },
      rules: {
      },
      processPercentage: 0,
      // 文件块大小 200M
      eachSize: 1024 * 1024 * 20,
      loading: {
        upload: false
      },
      fileLength: 0,
      isBool: false,
      isError: false
    }
  },

// 实现方法

// 关闭弹框的方法
onClose (type = 'dismiss') { if(type === 'dismiss') { this.isBool = false; } this.$emit('closeDialog', { name: this.dialoagName, type }); },
onChange (e) {
      this.form.file = Array.from(e.target.files)[0];
    },
    // 开始上传
    async onImport() {
      try {
        this.isError = false;
        this.loading.upload = true;
        // 将名字转成编码
        this.form.file.uid =  md5Hex(this.form.file.name);
        // 定义当前上传的索引
        this.form.file.chunk = 0;
        // 分片大小要求100M以下的分片大小设置为5M,以上的设置为20M
        if(this.form.size > 1024 * 1024 * 100) {
          this.eachSize = 1024 * 1024 * 20
        } else {
          this.eachSize = 1024 * 1024 * 5
        }
        this.fileLength = Math.ceil(this.form.file.size / this.eachSize);
 
        // 检测文件是否存在
        const { data } = await PackageImportService.getPackageImportUpload(this.form.file.uid);
        this.isBool = true;
        this.onUpload(this.form, data);
 
      } catch (error) {
        console.log(error)
      }
    },
    // 合并分片
    async packageImportMerge() {
      try {
        // 合并分片
        this.processPercentage = 100;
        await PackageImportService.packageImportMerge(
          this.form.file.uid,
          this.fileLength,
          this.form.file.name,
          this.$route.params.appId,
          this.$route.params.planId
        );
        this.$message.success(`程序包[${this.form.file.name}]导入成功`);
        this.onClose('confirm')
      } finally {
        this.loading.upload = false;
      }
    },
    async onUpload({file}, chunk) {
      try {
        if(!this.isBool) return;
        // 当前字节
        const blobFrom = file.chunk * this.eachSize;
        // 获取文件块的终止字节
        const blobTo = (file.chunk + 1) * this.eachSize > file.size ? file.size : (file.chunk + 1) * this.eachSize;
        if (chunk) file.chunk = chunk;
 
        // 进度条数值
        this.processPercentage = Number((blobTo / file.size * 100).toFixed(1));
        // 合并分片
        if (file.chunk === this.fileLength) {
          this.packageImportMerge()
          return;
        }
        // 检查断点续传的分片存在与否
        const { data } = await PackageImportService.checkPackageImport(file.uid, file.chunk);
        // 片段存在跳过本次上传
        if (data) {
          file.chunk++;
          this.onUpload({file: file});
          return;
        }
        // 将分片数据上传
        let formData = new FormData();
        formData.set('file', file.slice(blobFrom, blobTo));
        await PackageImportService.packageImport(file.uid, file.chunk, formData);
        file.chunk++;
        this.onUpload({file: file});
 
      } catch (error) {
        this.loading.upload = false;
        this.isError = true;
      }
    }

  

猜你喜欢

转载自www.cnblogs.com/fczbk/p/12395025.html