Angular(5)httpclient observe和responseType:'blob'

Chr*_*ris 13 angular angular-httpclient

上下文:我正在尝试从后端下载二进制文件(需要将一些数据发布为json-body),并使用内容处置标头中后端指定的文件名保存文件保护程序.要访问标题,我想我需要HttpResponse.

但是我无法使用HttpClient.post<T>(...): Observable<HttpResponse<T>>;带有Blob的angular 方法.

我打电话的时候

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"'.
Run Code Online (Sandbox Code Playgroud)

当我把选项放在一个自己的对象中,如/sf/answers/3361165671/所示(但没有"as"...)帖子(...):Observable被调用,我不能访问标题.

顺便说一句,即使是return this.http.get<Blob>('backendUrl', {responseType: 'blob'});/sf/answers/3281768521/中看到的简单示例也不适用于我.

使用的版本

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

fun*_*zer 39

使用时observe:response,不要键入call(post<Blob>(...)),因为返回的Observable将是HttpResponse.所以这应该工作:

this.httpclient.post('MyBackendUrl', 
    params,
    {observe: 'response', responseType: 'blob'}
);
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,是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>>;
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.我没有意识到添加`responseType:'blob'`会隐式地将结果更改为Observable <Blob>/Obserrvable <HttpResponse <Blob >> (6认同)

Kis*_*nav 13

其他答案是正确的,但他们缺少示例。

当设置 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;
  }));
Run Code Online (Sandbox Code Playgroud)

这里http是HttpClient的实例,saveAs()是与OP相同的FileSaver npm包的方法。

还有一个问题,您可能在 result.headers 中只有5 个标头(Cache-Control、Pragma 等),而不是您的自定义标头,例如x-filename.

这个 CORS 背后的原因。基本上,CORS 不允许浏览器访问多个标头(在上面的链接中列出)。

因此,解决这个问题,您必须更改服务器/API 以随请求发送Access-Control-Expose-Headers标头。


小智 5

你可以像

responseType: 'blob' as 'json'
Run Code Online (Sandbox Code Playgroud)