【问题标题】:Send files over angular Http sequentially (serially) one by one in angular using rxjs concatMap() operator使用 rxjs concatMap() 运算符按角度顺序(串行)一个接一个地通过角度 Http 发送文件
【发布时间】:2020-07-11 15:57:44
【问题描述】:

我正在尝试使用 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上尝试了很多解决方案。

【问题讨论】:

    标签: angular amazon-s3 rxjs observable httpclient


    【解决方案1】:

    您可以尝试使用 RxJS 的 from 函数和 concatMap 运算符。 from 一个一个地发出数组中的项目,而 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')
    );
    

    【讨论】:

    • 嗨,迈克尔,感谢您的回答。但是我收到错误,因为属性 ** 'url' 在类型 'Observable' 上不存在。** 我猜这没问题,因为在 uploadFilesByLink(res.url, file) 中, res 实际上是我得到的响应订阅 generateUrl(this.uniqueId, file) 后。请帮忙。
    • 我基于您的声明uploadFilesByLink(res1.url, file)。但是看到你的函数generateUrl() 它不会像你试图获取它那样返回具有url 属性的对象。而是直接做this.uploadsService.uploadFilesByLink(url, file)。我已经更新了答案。
    • 它返回一个带有 url 属性的对象,该 url 需要传递给 uploadFilebyLink 函数。
    • 从您第一条评论的错误消息中,您显然不是返回一个对象,而是一个 Observable。如果您想找到问题,则需要提供实际功能。
    【解决方案2】:

    我尝试过这种方式并且它的工作原理。

    上传.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');
              }
          }
    
        })
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 2017-07-31
      • 1970-01-01
      相关资源
      最近更新 更多