Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Angular / RxJs: Download Progress

I have working solution to getting download progress in Angular 13 / RxJs 7.

First I defined some enums:

export enum RequestType {
  get = 'GET',
  post = 'POST',
  put = 'PUT',
  delete = 'DELETE',
}

export enum ActionType {
  download = 1,
  upload
}

Next, I implemented a shared service to handle tracking progress:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

@Injectable({
  providedIn: 'root'
})
export class DownloadProgressService {

  percentDone = 0;
  actionType: ActionType;

  constructor(private http: HttpClient) { }

  downloadFile(uri: string, requestType: RequestType, actionType: ActionType, body: any): Observable<number> {

    this.actionType = actionType;

    const req = new HttpRequest(requestType, uri, body, {
      reportProgress: true,
      responseType: 'blob'
    });

    return this.http
      .request(req)
      .pipe(
        map(event => this.getPercentage(event)),
    );

  }

  public getPercentage(event: HttpEvent<any>): number {

    switch (event.type) {

      case HttpEventType.UploadProgress:

      // Downloading files will still trigger upload progress due to the back-and-forth, ignore this
      if (this.actionType !== ActionType.upload) {
        return 0;
      }

      // Compute and show the % done:
        if (event && event.total) {
          this.percentDone = Math.round(100 * event.loaded / event.total);
          return this.percentDone;
        } else {
          return 0;
        }

      case HttpEventType.DownloadProgress:

        if (event && event.total) {
          this.percentDone = Math.round(100 * event.loaded / event.total);
        }

        return this.percentDone;

      default:

        // Not an event we care about
        return this.percentDone;

    }
  }

}

Then, I simply subscribe to this and get proper progress of the download:

this.downloadService
  .downloadFile(url, RequestType.post, ActionType.download, body)
  .subscribe(progress => this.progress = progress);

This all works great, I get a progress bar with my component library that shows real progress.

The question is … how do I get the resulting file?

>Solution :

Instead of returning only the progress you could return an object that contains the progress percentage and the HTTP response.

return this.http.request(req).pipe(
  map(event => ({
    progress: this.getPercentage(event),
    response: event
  })),
);

Now in the subscription you can you use the object

this.downloadService
  .downloadFile(url, RequestType.post, ActionType.download, body)
  .subscribe({
    next: ({progress, response}) => {
      this.progress = progress;
      // use response
    },
    error: (error: any) => {
      // handle errors
    }
  });
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading