Search code examples
angulartypescriptangular-httpclient

Angular (5) httpclient observe and responseType: 'blob'


Context: I'm trying to download a binary file from a backend (that requires some data posted as json-body) and save it with file-saver using the filename specified by the backend in the content-disposition header. To access the headers I think I need the HttpResponse.

But I'm unable to use angular's HttpClient.post<T>(...): Observable<HttpResponse<T>>; method with a Blob.

When I call

this.httpclient.post<Blob>('MyBackendUrl', 
        params, 
        {observe: 'response', responseType: 'blob'});
the compiler complains about the 'blob' ('json' is accepted by the compiler):


error TS2345: Argument of type '{ observe: "response"; responseType: "blob"; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
  Types of property 'observe' are incompatible.
    Type '"response"' is not assignable to type '"body"'.

When I put the options in an own object as seen in https://stackoverflow.com/a/48016652/2131459 (but without the "as" ...) the post(...):Observable is called and I cannot access the headers.

Btw, even the simple example return this.http.get<Blob>('backendUrl', {responseType: 'blob'}); as seen e.g. in https://stackoverflow.com/a/46882407/2131459 doesn't work for me.

Versions used

  • Angular Version: 5.0.3 (will be updated to latest 5 in a week or so)
  • typescript: 2.4.2
  • webpack: 3.8.1

Solution

  • When using observe:response, don't type the call (post<Blob>(...)), as the returned Observable will be of HttpResponse. So this should work:

    this.httpclient.post('MyBackendUrl', 
        params,
        {observe: 'response', responseType: 'blob'}
    );
    

    Why this happens, is there's two versions of the post method, one with a generic type, one without:

    /**
         * Construct a POST request which interprets the body as JSON and returns the full event stream.
         *
         * @return an `Observable` of all `HttpEvent`s for the request, with a body type of `T`.
         */
        post<T>(url: string, body: any | null, options: {
            headers?: HttpHeaders | {
                [header: string]: string | string[];
            };
            observe: 'events';
            params?: HttpParams | {
                [param: string]: string | string[];
            };
            reportProgress?: boolean;
            responseType?: 'json';
            withCredentials?: boolean;
        }): Observable<HttpEvent<T>>;
        /**
         * Construct a POST request which interprets the body as an `ArrayBuffer` and returns the full response.
         *
         * @return an `Observable` of the `HttpResponse` for the request, with a body type of `ArrayBuffer`.
         */
        post(url: string, body: any | null, options: {
            headers?: HttpHeaders | {
                [header: string]: string | string[];
            };
            observe: 'response';
            params?: HttpParams | {
                [param: string]: string | string[];
            };
            reportProgress?: boolean;
            responseType: 'arraybuffer';
            withCredentials?: boolean;
        }): Observable<HttpResponse<ArrayBuffer>>;