Angular(5)httpclient观察和响应类型:' blob'

时间:2018-03-16 11:06:08

标签: angular angular-httpclient

上下文:我尝试从后端下载二进制文件(需要将一些数据发布为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 {{}}对我不起作用。

使用的版本

  • Angular Version:5.0.3(将在一周左右更新为最新的5个)
  • 打字稿:2.4.2
  • webpack:3.8.1

3 个答案:

答案 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'