前端实现多文件上传,断点续传

一、获取key

getKeyHanlder(obj, file, val) {
  //   this.uploadDisabled = true;
  if (this.timer) {
    this.clearTimeoutHandle();
  }
  breakpointGetKey(obj).then((res) => {
    if (res.code == "200") {
      this.uploadUrl = res.data.uploadUrl;
      this.checkUrl = res.data.checkUrl;
      this.uploadKey = res.data.key;
      this.randomName = res.data.fileName;
      var formData = new FormData(); // 当前为空
      formData.append("file", file.raw);
      formData.append("key", this.uploadKey);
      formData.append("regionId", this.upid);
      this.changeFile(file, this.uploadUrl,res.data);
    } else {
      //   this.uploadDisabled = false;
    }
  });
},

二、创建切片

 const chunkSize = 5 * 1024 * 1024; // 每个块的大小为 5MB
  const fileSize = file.size; // 文件大小
  const chunks = Math.ceil(fileSize / chunkSize); // 总块数
  // 切片个数
  this.slicesNum = chunks;
  // 创建切片
  let partList = [],
    partsize = chunkSize || file.size / this.slicesNum;
  for (let i = 1; i <= this.slicesNum; i++) {
    const start = (i - 1) * partsize;
    const end = Math.min(start + partsize, fileSize);
    let item = {
      // chunk: file.slice(cur, Math.min(file.size, cur + partsize)),
      chunk: file.slice(start, end),
      filename: `${hash}_${i}.${suffix}`,
      chunkNumber: `${i - 1}`,
      // file: file.slice(cur, Math.min(file.size, cur + partsize)),
      file: file.slice(start, end),
    };
    // cur += partsize;
    partList.push(item);
  }
  this.requestData = {
    fileMd5: hash,
    name: this.randomName,
    size: file.size,
    totalChunks: this.slicesNum,
    chunkSize: partsize,
    fileName: file.name,
    uploadKey: reqKeyData.key, // 后台需要的key
  };
  let obj = {
    total: 0,
    abort: false,
    btn: false,
    partList: partList,
    uploadErr: false, //是否上传失败
    status: 1, //上传状态
  };
  let fileObj = { ...this.requestData, ...obj };
  //文件列表
  this.openlistnum.push(fileObj);
  this.isUploading = true;
  this.sendRequest(fileObj);

三、请求集合

async sendRequest(element) {
      element.uploadSuc = false;
      // 根据100个切片创造100个请求集合
      let requestList = [];
      try {
        element.partList.forEach((item, index) => {
          // 每一个函数都发送一个切片请求
          let fn = async (chunkNumber) => {
            let formData = new FormData(),
              shardFile = new SparkMD5.ArrayBuffer(),
              shardFileBuffer = await fileParse(item.chunk, "buffer"),
              shardFileHash;
            shardFile.append(shardFileBuffer);
            shardFileHash = shardFile.end();
            formData.append(
              "chunk",
               element.reqNextChunkNumber ?  element.reqNextChunkNumber : item.chunkNumber
            );
            formData.append("file", item.file);
            formData.append("chunks", element.totalChunks);
            formData.append("md5", element.fileMd5);
            formData.append("name", element.name);
            formData.append("size", element.chunkSize);
            formData.append("key", element.uploadKey);
            return breakpointUpLoadFile(this.uploadUrl, formData).then(
              (res) => {
                const { code, data } = res;
                if (code == 206) {
                  // element.total += parseInt(100 / element.totalChunks);
                  //进度
                  element.total = parseInt(
                    (res.data.chunkNumber / element.totalChunks) * 100
                  );
                  // 传完的切片我们把它移除掉
                  if(data.chunkNumber){
                    element.partList.shift();    
                    element.reqNextChunkNumber = res.data.chunkNumber          
                  }
                  return data.chunkNumber;
                } else if (code == 200) {
                  this.$message.success("上传成功");
                  element.uploadSuc = true;
                  element.total = 100;
                  element.status = 0;
                  element.uploadErr = false;
                  this.$parent.gettableList();
                  this.$parent.getPage(2, this.upid, this.USER_id);
                  this.closeUploadInfo();
                } else {
                  throw Error(`We've found the target element.`);
                }
              }
            );
          };
          requestList.push(fn);
        });
      } catch (err) {}
      let i = 0;
      let send = async (params) => {
        if (params.abort) return;
        if (i >= requestList.length && !params.uploadSuc) {
          this.$message.warning("上传失败,请重新上传");
          params.total = 0;
          params.status = 0;
          params.uploadErr = true;
          this.closeUploadInfo();
          return;
        }
        if (params.uploadSuc) {
          params.status = 0;
          params.total = 100;
          params.uploadErr = false;
          return;
        }
        await requestList[i]().then((res) => {
        });
        i++;
        send(params);
      };
      send(element);
    },

四、暂停,续传

handleBtn(params) {
      if (params.btn) {
        params.abort = false;
        params.btn = false;
        this.sendRequest(params);
        return;
      }
      params.btn = true;
      params.abort = true;
    },

欢迎访问微信小程序“WEB前端宝典”,高频面试题,面试必备。在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值