使用 rxjs concatMap() 运算符在 angular 中一个接一个地通过 angular Http 发送文件

Send files over angular Http sequentially (serially) one by one in angular using rxjs concatMap() operator

我正在尝试使用 prefetchedUrl 将文件按顺序上传到 S3 存储桶。

generateUrl() 函数用于为每个要上传的文件生成唯一的 url。它需要一个 uniqueId(静态的)和一个文件名

  generateUrl(uniqueId, file) {
    var ext = (file.name).split(/\.(?=[^\.]+$)/);
    console.log(ext);
    return this.http.get<any>(`${this.baseURL}/v1/secure/upload/signed/${uniqueId}?filename=${file.name}.${ext}`);
  }

fileUpload() 函数用于上传文件。它需要由 generateUrl() 函数生成的唯一 url 和要上传的文件。

  uploadFilesByLink(url, file) {
    return this.http.put(url,file, {
      headers: { "Content-Type": file.type },
      reportProgress: true,
      observe:'events'
    })
  }

现在我要做的是 -

this.filesArray.forEach((file,index)=>{
     this.uploadsService.generateUrl(this.uniqueId, file)
        .pipe(
          concatMap(res1 => this.uploadsService.uploadFilesByLink(res1.url, file))
        ).subscribe(res2 => console.log(this.filesArray.indexOf(file),res2));
     })

但这是并行上传文件。 请帮忙。 我在 google.

上尝试了很多解决方案

您可以尝试使用 RxJS from function along with the concatMap operator. from emits items in an array one by one as opposed to RxJS of 函数,它不会展平输入并将数组作为单个通知发出。

尝试以下方法

from(this.filesArray).pipe(
  concatMap(file => {
    const url = this.uploadsService.generateUrl(this.uniqueId, file);
    return this.uploadsService.uploadFilesByLink(url, file);
  })
).subscribe(
  res => console.log(res),
  err => // always good practice to handle HTTP errors,
  () => console.log('complete')
);

我试过这种方法,效果很好。

upload.service.ts

  generateUrl(uniqueId, file) {
    console.log(file);
    var ext = (file.name).split(/\.(?=[^\.]+$)/);
    console.log(ext);
    return this.http.get<any>(`${this.baseURL}/v1/secure/upload/signed/${uniqueId}?filename=${file.name}.${ext}`)
      .pipe(
        map(
          res => {
           return {
             "url": res.url,
             "file":file
            }
          }
        )
      )
  }

上传-home.component.ts

 this.subscription = from(this.filesArray).pipe(
      concatMap(file => this.uploadsService.generateUrl(this.uniqueId, file)),
      concatMap(response => this.uploadsService.uploadFilesByLink(response.url, response.file))
    ).subscribe((event: HttpEvent<any>) => {

      switch (event.type) {
        case HttpEventType.Sent:
          console.log(' sent');
          break;
        case HttpEventType.ResponseHeader:
          console.log(' response header has been received');
          break;
        case HttpEventType.UploadProgress:
          // this.eventLoaded = event.loaded;
          this.progressInfo[this.it] = Math.round((event.loaded / event.total) * 100);
          console.log(event.loaded / event.total * 100);
          break;
        case HttpEventType.Response:
          // this.eventLoaded1 += this.eventLoaded;
          this.it++;
          console.log('it', this.it);

          this.responseArray.push(this.it);

          console.log('Uploaded');
          console.log(this.responseArray);

          // console.log(this.responseArray.length, this.filesArray.length);

          if (this.responseArray.length === this.filesArray.length) {
            console.log(this.emailOptions);

            if (this.emailOptions) {
              const controls = this.formGroup.controls;
              const from_email = controls.email_from.value;
              const to_email = controls.email_to.value;
              const message = controls.message.value;
              this.uploadsService.uploadFilesByEmail({
                "from_email": from_email,
                "to_email": [to_email],
                "message": message
              }, this.uniqueId).then(res => {
                this.uploadsService.afterUpdatingEmail(this.uniqueId).then(res => {
                  console.log('Uploaded By Email');

                  console.log(res);
                  this.it = 0;
                  this.filesArray = [];
                  this.fileSize = 0;
                  this.responseArray = [];
                  this.requestArrayLink = [];
                  this.subscription.unsubscribe();
                  this.successScreen = true;
                })
              })
            }
            else {
              this.it = 0;
              this.filesArray = [];
              this.fileSize = 0;
              this.responseArray = [];
              this.requestArrayLink = [];
              this.subscription.unsubscribe();
              console.log('Uploaded by Link');
              this.successScreen = true;
            }
          }
          else {
            console.log(this.it, 'uploaded');
          }
      }

    })
}