Search code examples
angularamazon-s3rxjsobservablehttpclient

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


I'm trying to upload files using a prefetchedUrl to S3 bucket sequentially.

generateUrl() function used to generate a unique url for each file to be upload. It takes a uniqueId (which is static) and a filename

  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() function used to upload files. It takes unique url generated by the generateUrl() function and a file to be uploaded.

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

Now what I'm trying to do is -

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));
     })

But this is uploading files parallely. Please help. I have tried many solutions on google.


Solution

  • I tried this way and its working.

    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
                }
              }
            )
          )
      }
    

    upload-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');
              }
          }
    
        })
    }