上下文:我尝试从后端下载二进制文件(需要将一些数据发布为json-body),并使用内容处置头中后端指定的文件名保存文件保护程序。要访问标题,我认为我需要HttpResponse。
但是我无法使用带有Blob的角度HttpClient.post<T>(...): Observable<HttpResponse<T>>;
方法。
当我打电话
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"'.
当我将选项放在https://stackoverflow.com/a/48016652/2131459中看到的自己的对象中时(但没有&#34; as&#34; ...)帖子(...):Observable被调用,我不能访问标题。
顺便说一句,即使是简单的例子return this.http.get<Blob>('backendUrl', {responseType: 'blob'});
,例如https://stackoverflow.com/a/46882407/2131459 {{}}对我不起作用。
使用的版本
答案 0 :(得分:33)
使用observe:response
时,请勿键入调用(post<Blob>(...)
),因为返回的Observable将为HttpResponse。所以这应该有效:
this.httpclient.post('MyBackendUrl',
params,
{observe: 'response', responseType: 'blob'}
);
为什么会发生这种情况,是post方法的两个版本,一个是泛型类型,一个没有:
/**
* 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>>;
答案 1 :(得分:8)
其他答案是正确的,但它们缺少示例。
主要答案,首先,当设置responseType时,响应的返回类型将更改为Blob。要解决此问题,请添加observe: 'response'
,它返回HTTPResponse。
示例: 我偶然发现了这个问题,花了6个小时来解决。
因此,在这里,我举一个例子来从标题获取文件名并下载文件:
downloadPDF(url: string): Observable<any> {
return this.http.get<any>(url, { responseType: 'blob', observe: 'response' }).pipe(
map((result:HttpResponse<Blob>) => {
console.log(result);
saveAs(result, "Quotation.pdf");
return result;
}));
这里http
是HttpClient的实例,saveAs()
是FileSaver npm包中与OP相同的方法。
还有一个问题,您可能在result.headers中仅得到5 headers(Cache-Control, Pragma, etc),而没有自定义标题,例如x-filename
。
此CORS背后的原因。基本上,CORS不允许浏览器访问的标题超过完整的标题(在上面的链接中列出)。
因此,您必须更改服务器/ API才能发送带有请求的 Access-Control-Expose-Headers 标头。
答案 2 :(得分:6)
您可以像使用
responseType: 'blob' as 'json'