angular中切片上传大文件

原本使用的是ng-zorro中upload上传组件上传文件,可是后面上传文件过大,上传速度慢,要求改成切片上传。

原本的上传组件不适合开发需求,改成原生的input上传,添加了取消上传功能,html代码如下:

<div style="display: flex;align-items: center;justify-content: flex-start">
   <div style="width: 30%">
       <button nz-button nzType="primary" (click)="clickUpload()" [disabled]="progerssShow">
          <i nz-icon nzType="plus" nzTheme="outline"></i>上传课件
       </button>
       <span class="operaTao" style="margin-left: 15px" (click)="cancelUpload()" [hidden]="!progerssShow">取消</span>
       <input accept="application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document, audio/mp4,video/mp4,application/pdf,video/x-msvideo" (change)="inputFileChange($event)" type="file" id="fileImport" style="display: none">
  </div>
  <div style="width: 40%;position: relative;left: -80px;" [hidden]="!progerssShow">
      <nz-progress [nzPercent]="fileProgress" nzStatus="active"></nz-progress>
  </div>
</div>

逻辑部分代码如下:

 /*上传文件点击,触发input的click事件*/
  clickUpload() {
    $('#fileImport').click();
    this.isCancel = false;
  }

/*选择文件,切片上传*/
  inputFileChange(e): void {
    this.firmwareFileList = null;
    this.fileLast = null;
    this.fileObj = null;
    this.classSaveObj = new SaveExamObj();
    this.examList = [];
    const files = e.target.files;
    if (files && files[0]) {
      const file = files[0];
      this.firmwareFileList = file;
      // 根据文件大小进行切片,这里是当文件大于100M时,按照文件大小分成100片,小于时,切成每片1M
      if (file.size > 1024*1024*100) {
        this.bytesPerPiece = Math.floor(file.size / 100);
      } else {
        this.bytesPerPiece = 1024 * 1024 *1;
      }

      this.progerssShow = true;
      this.fileProgress = 0;
      let start = 0;
      let index = 0;
      setTimeout(() => {
        this.loopSend(this.firmwareFileList, start, index); // 调用分片上传函数
      }, 100);
      e.target.value = '';
    }
  }

// 分片上传函数,这里调用后台接口需要和后端协商如何传参数,这里是没传一片,后端会返回下一片的序号,用于保存当前文件上传进度,使得文件上传如果中断,下次选择相同的文件时,继续之前的进度上传
loopSend(item, start, index) {
    if (this.isCancel) { // 取消上传
      return;
    }

    let that = this;
    const size = item.size;
    const finame = item.name;

    that.totalPieces = Math.ceil(size / that.bytesPerPiece); //计算文件切片总数
    const filekey = 'yxsource' + item.name + item.size + that.totalPieces;
    const filekey1 = Md5.hashStr(filekey).toString();

    if(start >= size){
      return;
    }//退出循环
    let end = start + that.bytesPerPiece;
    if(end > size) {
      end = size;
    }
    var chunk = item.slice(start, end); //切割文件
    var sliceIndex= index; //分片索引(第几个分片)

    //存业务属性
    var formData = new FormData();
    formData.append("file", chunk); //文件分片
    formData.append('moduleName', 'yxsource');
    formData.append("fileName", finame);//文件名
    formData.append("sliceIndex",sliceIndex.toString());//分片索引
    formData.append("totalPieces",that.totalPieces.toString());//切片总数
    formData.append('key', filekey1);

    this.httpclient.post(this.uploadUrlMaterial, formData, {
      responseType: 'json',
      headers: new HttpHeaders({
        Authorization: StorageUtil.getLocalStorage('token')
      }),
    }).subscribe(res => {
      // @ts-ignore
      if (res.status === StatusEnum.SUCCESS) {
        // @ts-ignore
        let sIdx = res.datas.sliceIndex; // 后端返回的下次上传的分片序号
        if (Number.parseInt(sIdx) != -1) {
          that.fileProgress = Math.floor(index / that.totalPieces * 100);  // 上传进度条进度
          index = Number.parseInt(sIdx);
          start = index * that.bytesPerPiece;

          that.loopSend(item, start, index)
        } else {
          // 文件上传完成===需要处理的地方
          that.fileProgress = 100;
          this.progerssShow = false;
          
        }
      } else {
        this.fileProgress = 0;
        this.progerssShow = false;
        this.isCancel = true; // 是否取消
      }
    });
  }


/*取消上传,只要不让循环继续就行*/
  cancelUpload() {
    this.isCancel = true;
    this.fileProgress = 0;
    this.progerssShow = false;
  }

效果如下:

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值