10

I am using Angular 4.3.2 and the new HttpClient to download a file sent as a stream, and I need to get the headers (particularly, Content-Disposition), but they don't seem to be present in the response even though I can see the headers being correctly sent with the request in Chrome's dev tools.

This is the code:

downloadDocument(documentId: number) {
    const downloadDocumentUrl = `${ this.config.apiUrls.documents }/${ documentId }`;
    const downloadRequest = new HttpRequest('GET', downloadDocumentUrl, {
        reportProgress: true,
        responseType: 'blob'
    });

    let percentageDownloaded = 0;
    this.http.request(downloadRequest).subscribe(
        (event: HttpEvent < any > ) => {
            if (event) {
                switch (event.type) {
                    case HttpEventType.ResponseHeader:
                        const contentDispositionHeader = event.headers.get('Content-Disposition');
                        console.log(contentDispositionHeader); // Always null here although I expected it to be there.
                        break;

                    case HttpEventType.DownloadProgress:
                        if (event.total) {
                            percentageDownloaded = Math.round((event.loaded / event.total) * 100);
                        }
                        break;

                    case HttpEventType.Response:
                        const downloadedFile: Blob = event.body;
                        fileSaverSaveAs(downloadedFile, `${ documentId }.pdf`, true); // This is where I'd like to use content-disposition to use the actual file name.
                        break;
                }
            }
         ,
        (err) => {}
    );
}

When this code gets called, Chrome reports in the network tab of dev tools the following response headers:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:4200
Content-Disposition:attachment; filename=doc5619362.pdf; filename*=UTF-8''doc5619362.pdf
Content-Length:88379
Content-Type:application/pdf
Date:Thu, 03 Aug 2017 09:43:41 GMT
Server:Kestrel
Vary:Origin
X-Powered-By:ASP.NET

Any ideas on how I can access all the headers present in the response? It is not just Content-Disposition that is not present, all of the other headers are not there except for Content-Type.

Thanks!

UPDATE

Here is a working Plunker demonstrating the issue: https://plnkr.co/edit/UXZuhWYKHrqZCZkUapgC?p=preview

Ceottaki
  • 694
  • 1
  • 9
  • 17

1 Answers1

27

The problem is not Angular, is the CORS handshaking: If the server does not explicitly allow your code to read the headers, the browser will hide them from it. The server must add in its responses the header Access-Control-Expose-Headers:<header_name>,<header-name2> in order to let you to read them, but currently it only allows to do a request and to read the response's body by adding Access-Control-Allow-Origin

Pablo Lozano
  • 10,122
  • 2
  • 38
  • 59
  • Thanks for the answer, @Pablo. Unfortunately, on my real scenario CORS is allowed just fine and the file downloads just fine, but still no headers. I should be still getting headers though, in that Plunkr. I could not find a file to point to that would allow CORS for the example. – Ceottaki Aug 03 '17 at 11:04
  • Are you sure?I mean then the plunkr scenario is not a valid one, that header is not present there so any other problem cannot be reproduced there – Pablo Lozano Aug 03 '17 at 11:05
  • I've updated the plunkr to a request that allows CORS: https://plnkr.co/edit/UXZuhWYKHrqZCZkUapgC?p=preview – Ceottaki Aug 03 '17 at 11:12
  • As I said, your plunkr allows CORS (access-control-allow-origin), but the header to allow other headers (Access-Control-Expose-Headers) is not present – Pablo Lozano Aug 03 '17 at 11:26
  • Would the headers show up in the network tab in Chrome Dev Tools if CORS wasn't allowing them through? – Ceottaki Aug 03 '17 at 16:35
  • 1
    Yes, they would, because they are sent by the server. But Chrome would hide them from your code due to CORS restrictions (the server must explicitly expose them) – Pablo Lozano Aug 04 '17 at 07:49
  • Ok, thanks, I will investigate this. My backend code is using ASP.NET Core and my policy is built with "AllowAnyHeader", so in theory, they should be available, but I'll look further into it and will try it without CORS as well, thanks. – Ceottaki Aug 04 '17 at 14:33
  • 1
    Allow any header (request headers are accepted) is something totally different from "Expose any header" (response headers can be read by anyone) – Pablo Lozano Aug 04 '17 at 14:39