Let´s assume, we are downloading file using HTTP POST method. We want to call another method to show download progress to end user until file download complete. How to use reportProgress in HttpClient for this?
Solution:
- We need to use
reportProgress: trueto show some progress of anyHTTPrequest - If we want to see all events, including the progress of transferts , we need to use
observe: 'events'option as well and return anObservableof typeHttpEvent. - Then we can catch all the
events(DownloadProgress, Response..etc)in the component method.
downfile(file: any): Observable<HttpEvent<any>>{
const options = {
responseType: 'blob' as const,
reportProgress: true,
observe: "events" as const,
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
return this.http.post(this.url , app, options);
}
Then in component we can catch all the events as below.
this.myService.downfile(file)
.subscribe(event => {
if (event.type === HttpEventType.DownloadProgress) {
const percentDone = Math.round(100 * event.loaded / event.total);
console.log("download in progress ====> " + percentDone + "%");
}
if (event.type === HttpEventType.Response) {
console.log("donwload completed");
}
});
PS-1: there are different kinds of HttpEvent.
enum HttpEventType {
Sent
UploadProgress
ResponseHeader
DownloadProgress
Response
User
}
PS-2 : (OBSERVE AND RESPONSE TYPES) ==> The types of the observe and response options are string unions, rather than plain strings.
options: {
…
observe?: 'body' | 'events' | 'response',
…
responseType?: 'arraybuffer'|'blob'|'json'|'text',
…
}
This can cause confusion. For example:
// this works
client.get('/foo', {responseType: 'text'})
// but this does NOT work
const options = {
responseType: 'text',
};
client.get('/foo', options)
In the second case, TypeScript infers the type of options to be {responseType: string}. The type is too wide to pass to HttpClient.get which is expecting the type of responseType to be one of the specific strings. HttpClient is typed explicitly this way so that the compiler can report the correct return type based on the options you provided.
Use as const to let TypeScript know that you really do mean to use a constant string type:
const options = {
responseType: 'text' as const,
};
client.get('/foo', options);
