Как обрабатывать ошибку для ответа Тип blob в HttpRequest
Я вызываю http-запрос с использованием httpClient и использую тип ответа как "blob", но проблема в том, что когда он идет в блоке с ошибкой, тип ответа остается "blob". Это вызывает проблему с моей обработкой ошибок.
this.httpClient.get('http://m502126:3000/reports/perdate', {
observe: 'body',
responseType: 'blob',
params: new HttpParams().set('START_DATE', startDate)
.set('END_DATE', endDate)
.set('MIXER', mixer)
.set('ATTACH', 'true')
}).subscribe(data => {
console.log(data);
},
error => {
console.log(error);
}
)
проблема в том, что я устанавливаю тип запроса as'blob, а тип ошибки - любой. Поэтому, когда ошибка возникает и идет в блоке с ошибкой, тип ответа остается "blob". Как справиться с этим?
Ответы
Ответ 1
Я столкнулся с той же проблемой. Чтобы обработать ответ об ошибке из запроса BLOB-объекта, вам необходимо проанализировать содержимое ошибки через FileReader
Это известная угловая проблема, и более подробную информацию можно прочитать там. Вы также можете найти различные решения для вашей проблемы.
Например, вы можете использовать эту функцию для анализа вашей ошибки в JSON:
parseErrorBlob(err: HttpErrorResponse): Observable<any> {
const reader: FileReader = new FileReader();
const obs = Observable.create((observer: any) => {
reader.onloadend = (e) => {
observer.error(JSON.parse(reader.result));
observer.complete();
}
});
reader.readAsText(err.error);
return obs;
}
и используйте это так:
public fetchBlob(): Observable<Blob> {
return this.http.get(
'my/url/to/ressource',
{responseType: 'blob'}
).pipe(catchError(this.parseErrorBlob))
}
Ответ 2
В ответе SplitterAlex упоминается угловая проблема, но не упоминается очень хорошее решение, предоставленное там JaapMosselman, которое включает создание HttpInterceptor
, который переведет BLOB-объект обратно в JSON.
Таким образом, вам не нужно реализовывать это в своем приложении, и когда проблема будет устранена, вы можете просто удалить ее.
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);
})
);
}
}
Объявите это в своем AppModule или CoreModule:
import { HTTP_INTERCEPTORS } from '@angular/common/http';
...
@NgModule({
...
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: BlobErrorHttpInterceptor,
multi: true
},
],
...
export class CoreModule { }
Ответ 3
Код от SplitterAlex работал для меня, но мне нужен был объект ошибки и код состояния тоже. Вот почему я немного изменил метод parseErrorBlob.
public parseErrorBlob(err: HttpErrorResponse): Observable<any> {
const reader: FileReader = new FileReader();
const obs = new Observable((observer: any) => {
reader.onloadend = (e) => {
const messageObject = JSON.parse(reader.result as string);
observer.error({
error : {
message : messageObject.message
},
message : messageObject.message,
status : err.status
});
observer.complete();
};
});
reader.readAsText(err.error);
return obs;
}