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: true
to show some progress of anyHTTP
request - If we want to see all events, including the progress of transferts , we need to use
observe: 'events'
option as well and return anObservable
of 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);