Angular 4.3.3 HttpClient:如何从响应的标头中获取值?

新手上路,请多包涵

(编辑器:VS Code;打字稿:2.2.1)

目的是获取请求响应的标头

假设服务中带有 HttpClient 的 POST 请求

import {
    Injectable
} from "@angular/core";

import {
    HttpClient,
    HttpHeaders,
} from "@angular/common/http";

@Injectable()
export class MyHttpClientService {
    const url = 'url';

    const body = {
        body: 'the body'
    };

    const headers = 'headers made with HttpHeaders';

    const options = {
        headers: headers,
        observe: "response", // to display the full response
        responseType: "json"
    };

    return this.http.post(sessionUrl, body, options)
        .subscribe(response => {
            console.log(response);
            return response;
        }, err => {
            throw err;
        });
}

HttpClient Angular 文档

第一个问题是我有一个打字稿错误:

 'Argument of type '{
    headers: HttpHeaders;
    observe: string;
    responseType: string;
}' is not assignable to parameter of type'{
    headers?: HttpHeaders;
    observe?: "body";
    params?: HttpParams; reportProgress?: boolean;
    respons...'.

Types of property 'observe' are incompatible.
Type 'string' is not assignable to type '"body"'.'
at: '51,49' source: 'ts'

确实,当我转到 post() 方法的 ref 时,我指向这个原型(我使用 VS 代码)

 post(url: string, body: any | null, options: {
        headers?: HttpHeaders;
        observe?: 'body';
        params?: HttpParams;
        reportProgress?: boolean;
        responseType: 'arraybuffer';
        withCredentials?: boolean;
    }): Observable<ArrayBuffer>;

但我想要这个重载的方法:

 post(url: string, body: any | null, options: {
    headers?: HttpHeaders;
    observe: 'response';
    params?: HttpParams;
    reportProgress?: boolean;
    responseType?: 'json';
    withCredentials?: boolean;
}): Observable<HttpResponse<Object>>;

所以,我试图用这个结构来修复这个错误:

   const options = {
            headers: headers,
            "observe?": "response",
            "responseType?": "json",
        };

它编译!但我只是得到了 json 格式的正文请求。

此外,为什么我必须放一个?某些字段名称末尾的符号?正如我在 Typescript 网站上看到的,这个符号应该告诉用户它是可选的?

我还尝试使用所有字段,不带和带 ?分数

编辑

我尝试了 Angular 4 get headers from API response 提出的解决方案。对于地图解决方案:

 this.http.post(url).map(resp => console.log(resp));

Typescript 编译器告诉 map 不存在,因为它不是 Observable 的一部分

我也试过这个

import { Response } from "@angular/http";

this.http.post(url).post((resp: Response) => resp)

它编译,但我得到一个不受支持的媒体类型响应。这些解决方案应该适用于“Http”,但不适用于“HttpClient”。

编辑 2

我还使用@Supamiu 解决方案获得了不受支持的媒体类型,所以这将是我的标题上的错误。所以上面的第二个解决方案(带有响应类型)也应该有效。但就个人而言,我认为将“Http”与“HttpClient”混合不是一个好方法,所以我会保留 Supamiu 的解决方案

原文由 SolidCanary 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

您可以观察完整的响应,而不仅仅是内容。为此,您必须将 observe: response 传递给函数调用的 options 参数。

 http
  .get<MyJsonData>('/data.json', {observe: 'response'})
  .subscribe(resp => {
    // Here, resp is of type HttpResponse<MyJsonData>.
    // You can inspect its headers:
    console.log(resp.headers.get('X-Custom-Header'));
    // And access the body directly, which is typed as MyJsonData as requested.
    console.log(resp.body.someField);
  });

查看 HttpClient 的文档

原文由 Supamiu 发布,翻译遵循 CC BY-SA 4.0 许可协议

下面的方法对我来说非常有效(目前是 Angular 10)。它还避免设置一些任意文件名,而是从 content-disposition 标头获取文件名。

 this._httpClient.get("api/FileDownload/GetFile", { responseType: 'blob' as 'json', observe: 'response' }).subscribe(response =>  {
    /* Get filename from Content-Disposition header */
    var filename = "";
    var disposition = response.headers.get('Content-Disposition');
    if (disposition && disposition.indexOf('attachment') !== -1) {
        var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        var matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
    }
    // This does the trick
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(response.body);
    a.download = filename;
    a.dispatchEvent(new MouseEvent('click'));
})

原文由 Tom el Safadi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题