0

This is something that should be easy to fix but right know my mind can't find a solution.

I've got a post like this:

getAccordo(filtro: Filter): Observable<Response>  {
    return this.http.post<Response>(`${this.ENDPOINT}/export`,
        filtro,
        {observe: 'response', responseType: 'blob' as 'json'}   
    )
        .catch(error => this.handleError(error));
}

And this is where I use it:

  public getAccordo(event: any): any {debugger;
    event.preventDefault();
    this.accordiService.getAccordo(this.filter).subscribe(
      res => {debugger;
        const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
        const anchor = document.createElement('a');
        anchor.href = window.URL.createObjectURL(blob);
        anchor.download = Utils.extractHeaders(res);
        anchor.click();
      },
      error => {
        console.log(error);
      }
    );
  }

When I look the chrome console I can see that in the headers there is a content-disposition: attachment; filename="esportazione_accordi_20180905.xlsx"

But in my 'res' this is missing.

Res

What id like to do is to get the filename and use it in anchor.download.

Thank you for the help if you need something more just ask.

EDIT

This is the headers that i get from the Response Headers, I dont see even 1 of them:

enter image description here

On the server side ive added: .header("Access-Control-Expose-Headers", "content-disposition") But still it doesnt work

EDIT 2:

Ok we are getting closer, I need to get the "filename" value at the end of the pic and assign that to anchor.download.

enter image description here

  • 2
    The response headers are *lazily parsed* - You'll need to actually attempt to get the header using `res.headers.get('Content-Disposition')` to see a result. – Kirk Larkin Sep 05 '18 at 09:30
  • ok so if I use res.headers.get('Content-Disposition') i get everything, one last step, how can i use the value that i need? Ill update the post again in a min to show you what i mean – Francesco Giberti Sep 05 '18 at 09:54
  • 1
    You can use regex for that - here's a really basic example: `const filename = /attachment; filename="(.+")/.exec(headerValue)[1];`. This assumes the regex is going to match - you can check the return value of the `exec` call for `null` before accessing it's second array element to be safe here. – Kirk Larkin Sep 05 '18 at 10:06
  • 1
    [Here](https://stackoverflow.com/questions/40939380/how-to-get-file-name-from-content-disposition)'s another question specifically on that filename parsing stuff. – Kirk Larkin Sep 05 '18 at 10:10

1 Answers1

5

In order to expose this header to your Angular XHR, the server will need to set the Access-Control-Expose-Headers response header to allow specifically access to the Content-Disposition header. The docs have more information on the subject:

By default, only the 6 simple response headers are exposed:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

If you want clients to be able to access other headers, you have to list them using the Access-Control-Expose-Headers header.

This means that your server needs to set the following header:

Access-Control-Expose-Headers: Content-Disposition

In Angular, using HttpClient, the response headers are lazily parsed - To get a specific header's value, you'll need to to get the header using something like this:

res.headers.get('Content-Disposition');
Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203