web-dev-qa-db-de.com

Verwendung der angle2 http-API zum Verfolgen des Upload- / Download-Fortschritts

Obwohl es in angle2 viele Ad-hoc-Bibliotheken gibt, die den Upload/Download-Fortschritt unterstützen, weiß ich nicht, wie ich den Fortschritt beim Upload/Download mit der nativen Angular2-http-API anzeigen kann.

Der Grund, warum ich native http-API verwenden möchte, ist, weil ich verwenden möchte

  1. http-Interceptors (http-API-Wrapper) um die native http-API, die die tatsächlich gesendete http-Anforderung validieren, zwischenspeichern und anreichern, z. B. this & this
  2. Außerdem ist die http-API von Angle wesentlich robuster als alle Ad-hoc-APIs

Es gibt dieser nette Artikel wie man einen Upload/Download mit der http-API von angle macht

Der Artikel erwähnt jedoch, dass es keinen nativen Weg gibt, den Fortschritt zu unterstützen.

Hat jemand versucht, mit http api den Fortschritt anzuzeigen?

Wenn nicht, kennen Sie ein Problem im angular Repo dafür?

18
Ashok Koyi

Ab den Versionen Angular 4.3.x und höher kann dies mit dem neuen HttpClient erreicht werden von @angular/common/http.

Lesen Sie den Abschnitt Fortschrittsereignisse abhören .

Einfaches Upload-Beispiel (kopiert aus dem oben genannten Abschnitt):

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

Und zum Herunterladen könnte es ungefähr so ​​sein:

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

Denken Sie daran, dass für den Fall, dass Sie einen Download überwachen, das Content-Length muss gesetzt sein, sonst kann die Anforderung nicht gemessen werden.

40

Ich würde vorschlagen, dass Sie das native JavaScript XHR verwenden, das als Observable verpackt ist. Es ist ziemlich einfach, es selbst zu erstellen:

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

Und so würde man es benutzen:

// 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();
3
borislemke