【问题标题】:Unable to view 'Content-Disposition' headers in Angular4 GET response无法在 Angular4 GET 响应中查看“Content-Disposition”标头
【发布时间】:2017-08-26 07:12:53
【问题描述】:

我正在尝试在我的 Angular 应用程序中下载一个 pdf 文件。服务器(JBoss)提供一个文件

Content-type : application/pdf and Content- Disposition

标题设置为附件。 我可以在提琴手响应中很好地看到这些标题。但是在我的订阅回调中,我看不到相同的标题。相反,标题包含两个属性,即: _headers and _normalizedHeaders

在进行 GET 调用时。我愿意:

`this._http.get(url, {responseType: 'arraybuffer'}).subscribe((file: Response)=>{

    //Cant find headers in file here

});`

我还尝试将 responseType 设置为 RequestContentType.Blob,但也没有任何区别。

对于我的下载实现,我有一段代码一直可以用 AngularJS 下载附件。我只是在这里努力阅读Content-Disposition 标头。

我也尝试设置{ observe : response },希望通过这种方式得到详细的回复。但是,由于某些原因,不允许在 GET options 中设置该属性。

我在 SO 上看到了很多答案并尝试了其中的大部分,但仍然无法获得标题。

P.S:直接在浏览器上点击 API 可以让我下载文件,这意味着我的 Java 代码很好,这让我想知道我上面的代码有什么问题。

请求建议。

【问题讨论】:

    标签: javascript angular browser download http-headers


    【解决方案1】:

    在Evans建议的Access-Control-Expose-HeaderssetExposedHeaders的帮助下,我可以实现如下文件下载。

    在您的 Java 代码中,您需要公开 Access-Control-Expose-Headers,这可以使用 CORS 来完成:

        CorsFilter corsFilter = new CorsFilter();
        corsFilter.setAllowedHeaders("Content-Type, Access-Control-Allow-Headers, Access-Control-Expose-Headers, Content-Disposition, 
        Authorization, X-Requested-With");
        corsFilter.setExposedHeaders("Content-Disposition");
    

    这将在服务器响应中公开所需的标头。

    在您的客户端上,您可以使用以下代码来处理响应:

        private processDownloadFile() {
                  const fileUrl = this._downloadUrl;
                  this.http.get(fileUrl, ResponseContentType.ArrayBuffer).subscribe( (data: any) => {
                    const blob = new Blob([data._body], { type: data.headers.get('Content-Type')});
                    const contentDispositionHeader = data.headers.get('Content-Disposition');
                    if (contentDispositionHeader !== null) {
                        const contentDispositionHeaderResult = contentDispositionHeader.split(';')[1].trim().split('=')[1];
                        const contentDispositionFileName = contentDispositionHeaderResult.replace(/"/g, '');
                        const downloadlink = document.createElement('a');
                        downloadlink.href = window.URL.createObjectURL(blob);
                        downloadlink.download = contentDispositionFileName;
                        if (window.navigator.msSaveOrOpenBlob) {
                            window.navigator.msSaveBlob(blob, contentDispositionFileName);
                        } else {
                            downloadlink.click();
                        }
                    }
                  });
        }   
    

    当然,我把所有东西都写在了一个地方。您可能希望模块化各种回调。

    希望有一天它对某人有所帮助。

    【讨论】:

    • 这对我有用,谢谢。对于 dotnet core 上的任何人,这是我在 startup.cs > ConfigureServices() 中的解决方案。 services.AddCors(c => { c.AddPolicy("CorsPolicy", options => options.SetIsOriginAllowed(s => s.Contains("localhost")).AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("Content-Disposition")); });
    • 遗憾的是,msSaveOrOpenBlob 已被弃用:( developer.mozilla.org/en-US/docs/Web/API/Navigator/…
    【解决方案2】:

    为了让您的服务器发送的任何自定义标头可以在 Angular(或任何其他 Web 应用程序)中访问,它必须存在于 Access-Control-Expose-Headers 中,否则您的浏览器不会将它传递给您的 Angular 应用程序,您也不会即使您的开发人员工具显示它存在,也可以检索它。

    【讨论】:

    • 我在 Java 中执行此操作,并且我将以下标头设置为我的 CORS 的一部分:corsFilter.setAllowedHeaders("Content-Type, Access-Control-Allow-Headers, Access-Control-Expose-Headers, Content-Disposition, Content-Length, Authorization, X-Requested-With"); 您还有其他建议吗?
    • 如果您仔细查看您的代码,您会注意到您只是设置了Access-Control-Allow-Headers,并将Access-Control-Expose-Headers 包括在允许的标头中。我不确定这是如何在 Java 中完成的,但我认为您还应该有类似 `corsFilter.setExposedHeaders("custom header, customer, header")
    • 我在现有代码中添加了corsFilter.setExposedHeaders("Content-Disposition, Content-Type");。这允许下载文件。但是,令人惊讶的是,如果您单击下载的文件,它只会弹出一个说Failed to load PDF document. 这熟悉吗?
    • Thankz @Evans :您的回答帮助我实现了所需的行为。发布详细答案。
    【解决方案3】:

    你可以这样试试

    我们需要这个包文件保护程序,你像“npm install file-saver --save”一样安装,然后你可以试试

    public downloadCSVFile(){
    this.downloadPdf().subscribe(
        (res) => {      
            saveAs(res,'test.pdf')
        }
    );
    }
    
    public downloadPdf(): any {
       let url='your url'
       let headers = new Headers();
       headers.append('Authorization', 'JWT ' + localStorage.getItem('id_token'));
       return this.http.get(url,{  headers: headers,responseType: ResponseContentType.Blob }).map(
        (res) => {
            return new Blob([res.blob()], { type: 'application/pdf' })
        })
    
    
      }
    

    您需要从支持的(JBoss 服务器)公开 “Content-Disposition” 的标头

    【讨论】:

    • 感谢@Robert,虽然我不是在寻找外部模块来实现它。我发布了对我的案子有帮助的代码。
    • 好的,超级@SaurabhTiwari
    猜你喜欢
    • 2018-10-30
    • 2010-11-03
    • 2021-10-23
    • 2013-02-10
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    相关资源
    最近更新 更多