Angular 5 manage http get with blob response and json errors

This is a known Angular issue, and in that thread JaapMosselman provides a very nice solution that involves creating an HttpInterceptor which will translate the Blob back to JSON.

Using this approach, you don’t have to do conversions throughout your application, and when the issue is fixed, you can simply remove it.

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class BlobErrorHttpInterceptor implements HttpInterceptor {
    public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req).pipe(
            catchError(err => {
                if (err instanceof HttpErrorResponse && err.error instanceof Blob && err.error.type === "application/json") {
                    // https://github.com/angular/angular/issues/19888
                    // When request of type Blob, the error is also in Blob instead of object of the json data
                    return new Promise<any>((resolve, reject) => {
                        let reader = new FileReader();
                        reader.onload = (e: Event) => {
                            try {
                                const errmsg = JSON.parse((<any>e.target).result);
                                reject(new HttpErrorResponse({
                                    error: errmsg,
                                    headers: err.headers,
                                    status: err.status,
                                    statusText: err.statusText,
                                    url: err.url
                                }));
                            } catch (e) {
                                reject(err);
                            }
                        };
                        reader.onerror = (e) => {
                            reject(err);
                        };
                        reader.readAsText(err.error);
                    });
                }
                return throwError(err);
            })
        );
    }
}

Declare it in your AppModule or CoreModule:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
...

@NgModule({
    ...
    providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: BlobErrorHttpInterceptor,
            multi: true
        },
    ],
    ...
export class CoreModule { }

Like probably most people, I wanted my error message synchronously. I dealt with the problem by putting it in an alert box:

(err:any) => { 

    // Because result, including err.error, is a blob,
    // we must use FileReader to display it asynchronously:
    var reader = new FileReader();
    reader.onloadend = function(e) {
      alert("Error:n" + (<any>e.target).result);
    }
    reader.readAsText(err.error);

    let errorMessage = "Error: " + err.status.toString() + " Error will display in alert box.";
    // your code here to display error messages.
},