我已经在Angular应用程序中创建了一个REST API调用,可以下载文件。
我正在将responseType设置为“ blob”,因为我希望得到一个响应文件。
但是,如果服务器上没有可用的文件,则响应的错误代码为404,即错误请求,正文中带有一些消息。
但是我无法从正文中解析该错误消息,因为HttpErrorResponse给了错误一个Blob对象。错误
如何从错误对象而不是blob获取实际主体。
还有任何方法可以配置角度,以便在api调用成功后将请求解析为blob,否则将其解析为json ???
希望获得解决方案
答案 0 :(得分:1)
如果返回的ContentType不同,则可以利用它来区分它是正确的二进制文件还是二进制格式的文本。
让我们考虑您有两个文件,一个服务处理您的请求的文件和一个执行业务逻辑的组件
在服务内部,您的下载方法如下:
public downloadFile(yourParams): Observable<yourType | Blob> {
return this._http.post(yourRequestURL, yourParams.body, {responseType: 'blob'}).pipe(
switchMap((data: Blob) => {
if (data.type == <ResponseType> 'application/octet-stream') {
// this is a correct binary data, great return as it is
return of(data);
} else {
// this is some error message, returned as a blob
let reader = new FileReader();
reader.readAsBinaryString(data); // read that message
return fromEvent(reader, 'loadend').pipe(
map(() => {
return JSON.parse(reader.result); // parse it as it's a text.
// considering you are handling JSON data in your app, if not then return as it is
})
);
}
})
);
}
在您的组件中
public downloadFile(params): void {
this._service.downloadFile(params)
subscribe((data: yourType | Blob) => {
if (data instanceof Blob) {
fileSaverSave(data, filename); // use fileSaver or however you are downloading the content
// add an import for saveAs (import { saveAs as fileSaverSave } from 'file-saver';)
} else {
// do your componnet logic to show the errors
}
})
}
如果愿意,可以将所有内容都包含在组件本身中。
答案 1 :(得分:1)
尝试一下
if(error.error instanceof Blob) {
error.error.text().then(text => {
let error_msg = (JSON.parse(text).message);
console.log(error_msg)
});
} else {
//handle regular json error - useful if you are offline
}
答案 2 :(得分:0)
您可以尝试使用单独的错误处理程序函数,该函数将响应返回为
T
,如下所示-
public handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
// TODO: send the error to remote logging infrastructure
console.error(error); // log to console instead
// TODO: better job of transforming error for user consumption
console.log(`${operation} failed: ${error.message}`);
// Let the app keep running by returning an empty result.
return of(result as T);
};
}
然后只需使用它来跟踪您的请求中的错误,如下所示-
return this.http.post(this.appconstants.downloadUrl, data, { responseType: 'blob' }).pipe(
map(this.loggerService.extractFiles),
catchError(this.loggerService.handleError<any>('downloadFile')) // <----
);
仅供参考,我上面用来返回文件的函数extractFiles
如下-
public extractFiles(res: Blob): Blob{
return res;
}
答案 3 :(得分:0)
参数: {观察:'response'} ,让您阅读完整的响应,包括标题。请参见以下说明:-
通过观察选项告诉HttpClient您想要完整的响应:
1. Go to Data > Text to Columns
2. Choose Delimited > Next
3. Choose Semicolon > Next
4. Choose General or Text, whichever you prefer.
5. Click Finish.
现在HttpClient.get()返回一个类型为HttpResponse的Observable,而不仅仅是JSON数据。
getConfigResponse(): Observable<HttpResponse<Config>> {
return this.http.get<Config>(this.configUrl, { observe: 'response' });
}
并得到这样的Error主体:-
this.configService.getConfigResponse()
// resp is of type `HttpResponse<Config>`
.subscribe(resp => {
// display its headers
const keys = resp.headers.keys();
this.headers = keys.map(key =>
`${key}: ${resp.headers.get(key)}`);
// access the body directly, which is typed as `Config`.
this.config = { ...resp.body };
});
从'rxjs / operators'导入{catchError};
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
};
参考:https://angular.io/guide/http:阅读完整的答复
相应地更改代码。
答案 4 :(得分:0)
为将来的访问者(由于标题是通用的):
如果后端在发生错误时返回JSON(理想情况下,在RFC 7807之后,这也意味着application/problem+json
内容类型),则error.error
是JSON对象,而不是字符串。因此,例如,要打印它,您首先需要将其字符串化:
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${JSON.stringify(error.error)}`);
我认为混乱之处始于正式的Angular documentation,其中包含以下声明:
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
但是,error.error
是一个JSON对象(在标准情况下),您将为正文打印[object Object]
而不是该JSON对象的字符串表示形式。如果尝试${error.error.toString()}
,则会产生无用的输出。