简体   繁体   中英

How to get the name of a file downloaded with Angular5

My response Headers is:

HTTP/1.1 200 OK
Content-Disposition: attachment; filename="file.docx"
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Thu, 26 Apr 2018 10:37:00 GMT
ETag: W/"c61-16301871843"
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Content-Length: 3169
Date: Thu, 26 Apr 2018 10:37:00 GMT
Connection: keep-alive

I tried this code,

 public download(id: string): Observable<Blob> {
    let headers = new Headers();
    const _baseUrl = (Api.getUrl(Api.URLS.download));
    headers.append('x-access-token', this.auth.getCurrentUser().token);
    headers.append('sale_id', id);
    return this.http.get(_baseUrl, { headers: headers, responseType: ResponseContentType.Blob})
      .map((res) => {
        console.log(res.headers) // show like in image
        return new Blob([res.blob()], { type: 'application/octet-stream' })
      });
  }

that show in console: 在此处输入图片说明

Didn't show Content-Disposition !!

How do I get the name of the file from the headers?

Your backend needs to return a specific header, Access-Control-Expose-Headers . If you don't, Angular doesn't expose the header, explaining why you can't see it.

You can find more information here (although it's a bit old) and even more information here

Hope this will save your time,

First import file-saver to your components.ts file

import { saveAs } from 'file-saver';

return this.http.get(url, { headers: {
  Accept: 'application/json',
  'Content-Type': 'application/json',
}, responseType: 'blob', observe: 'response' })
  .pipe().subscribe({
    next: (response: any) => {
      let fileName = 'file';
      const contentDisposition = response.headers.get('Content-Disposition');
      if (contentDisposition) {
        const fileNameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        const matches = fileNameRegex.exec(contentDisposition);
        if (matches != null && matches[1]) {
          fileName = matches[1].replace(/['"]/g, '');
        }
      }
      const fileContent = response.body;
      const blob = new Blob([fileContent], { type: 'application/octet-stream' });
      saveAs(blob, fileName);
    },
    error: (error) => {
      this.handleError(error);
    }
  });

Also, set API side header like

'Access-Control-Expose-Headers', 'Content-Disposition'

try this:

 (res: Response) => {
  const contentDisposition = res.headers.get('content-disposition') || '';
  const matches = /filename=([^;]+)/ig.exec(contentDisposition);
  const fileName = (matches[1] || 'untitled').trim();
  return fileName;
};

Actually, The response body in angular doesn't return all the data you may need. So we need to specify that we need the full response. To do that you need to add HTTPOptions with observe: "response" as 'body' in the service,

var HTTPOptions = {
     headers: new HttpHeaders({'Accept': 'application/pdf; charset=UTF-8',}),
     observe: "response" as 'body',// to display the full response & as 'body' for type cast
     'responseType': 'blob' as 'json'
 }

 return this.http.get(url, HTTPOptions);

Then you will be able to get the complete response, By subscribing to this method,

this.service.download().subscribe((result: HttpResponse<any>) => {
 console.log(result);
 console.log(result.headers.getAll('Content-Disposition'));
}, err => {});

You can refer more details in the Angular Documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM