Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use angular2 http API for tracking upload/download progress

Thus there are many ad hoc libraries supporting upload/download progress in angular2, I do not know how to use native angular2 http api to show progress while doing upload/download.

The reason why I want to use native http api is because I want to utilize:

  1. http interceptors (http API wrappers) around native http api that validate, cache & enrich the actual http request being sent such as this & this
  2. Angular's http api is much more robust than any ad hoc APIs

There is a nice article about how to do upload/download using angular's http api

But the article mentions that there is no native way to support progress.

Did anyone try using http api for showing progress?

If not, do you know an issue in the angular repo for this?

like image 905
Ashok Koyi Avatar asked Feb 14 '17 16:02

Ashok Koyi


2 Answers

As of Angular 4.3.x and beyond versions, it can be achieved using the new HttpClient from @angular/common/http.

Read the Listening to progress events section.

Simple upload example (copied from the section mentioned above):

    const req = new HttpRequest('POST', '/upload/file', file, {
      reportProgress: true,
    });

    http.request(req).subscribe(event => {
      // Via this API, you get access to the raw event stream.
      // Look for upload progress events.
      if (event.type === HttpEventType.UploadProgress) {
        // This is an upload progress event. Compute and show the % done:
        const percentDone = Math.round(100 * event.loaded / event.total);
        console.log(`File is ${percentDone}% uploaded.`);
      } else if (event instanceof HttpResponse) {
        console.log('File is completely uploaded!');
      }
    });

And for downloading, it might be something like pretty much the same:

    const req = new HttpRequest('GET', '/download/file', {
      reportProgress: true,
    });

    http.request(req).subscribe(event => {
      // Via this API, you get access to the raw event stream.
      // Look for download progress events.
      if (event.type === HttpEventType.DownloadProgress) {
        // This is an download progress event. Compute and show the % done:
        const percentDone = Math.round(100 * event.loaded / event.total);
        console.log(`File is ${percentDone}% downloaded.`);
      } else if (event instanceof HttpResponse) {
        console.log('File is completely downloaded!');
      }
    });

Remember in case that you're monitoring a download, the Content-Length has to be set, otherwise, there's no way to the request to be measured.

like image 133
Edmundo Rodrigues Avatar answered Oct 20 '22 10:10

Edmundo Rodrigues


I would suggest using the native JavaScript XHR wrapped as an Observable, it's fairly easy to create on your own:

upload(file: File): Observable<string | number> {

    let fd: FormData = new FormData();

    fd.append("file", file);

    let xhr = new XMLHttpRequest;

    return Observable.create(observer => {

        xhr.addEventListener("progress", (progress) => {

            let percentCompleted;

            // Checks if we can really track the progress
            if (progress.lengthComputable) {

                // progress.loaded is a number between 0 and 1, so we'll multiple it by 100
                percentCompleted = Math.round(progress.loaded / progress.total * 100);

                if (percentCompleted < 1) {
                    observer.next(0);
                } else {
                    // Emit the progress percentage
                    observer.next(percentCompleted);
                }
            }
        });

        xhr.addEventListener("load", (e) => {

            if (e.target['status'] !== 200) observer.error(e.target['responseText']);

            else observer.complete(e.target['responseText']);
        });

        xhr.addEventListener("error", (err) => {

            console.log('upload error', err);

            observer.error('Upload error');
        });

        xhr.addEventListener("abort", (abort) => {

            console.log('upload abort', abort);

            observer.error('Transfer aborted by the user');
        });

        xhr.open('POST', 'http://some-dummy-url.com/v1/media/files');

        // Add any headers if necessary
        xhr.setRequestHeader("Authorization", `Bearer rqrwrewrqe`);

        // Send off the file
        xhr.send(fd);

        // This function will get executed once the subscription
        // has been unsubscribed
        return () => xhr.abort()
    });
}

And this is how one would use it:

// file is an instance of File that you need to retrieve from input[type="file"] element
const uploadSubscription = this.upload(file).subscribe(progress => {
    if (typeof progress === Number) {
        console.log("upload progress:", progress);
    }
});

// To abort the upload
// we should check whether the subscription is still active
if (uploadSubscription) uploadSubscription.unsubscribe();
like image 3
borislemke Avatar answered Oct 20 '22 08:10

borislemke