Angular: How To Download A File From HttpClient?
Answer :
Blobs are returned with file type from backend. The following function will accept any file type and popup download window:
downloadFile(route: string, filename: string = null): void{ const baseUrl = 'http://myserver/index.php/api'; const token = 'my JWT'; const headers = new HttpHeaders().set('authorization','Bearer '+token); this.http.get(baseUrl + route,{headers, responseType: 'blob' as 'json'}).subscribe( (response: any) =>{ let dataType = response.type; let binaryData = []; binaryData.push(response); let downloadLink = document.createElement('a'); downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, {type: dataType})); if (filename) downloadLink.setAttribute('download', filename); document.body.appendChild(downloadLink); downloadLink.click(); } ) }
Try something like this:
type: application/ms-excel
/** * used to get file from server */ this.http.get(`${environment.apiUrl}`,{ responseType: 'arraybuffer',headers:headers} ).subscribe(response => this.downLoadFile(response, "application/ms-excel")); /** * Method is use to download file. * @param data - Array Buffer data * @param type - type of the document. */ downLoadFile(data: any, type: string) { let blob = new Blob([data], { type: type}); let url = window.URL.createObjectURL(blob); let pwa = window.open(url); if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') { alert( 'Please disable your Pop-up blocker and try again.'); } }
It took me a while to implement the other responses, as I'm using Angular 8 (tested up to 10). I ended up with the following code (heavily inspired by Hasan).
Note that for the name to be set, the header Access-Control-Expose-Headers
MUST include Content-Disposition
. To set this in django RF:
http_response = HttpResponse(package, content_type='application/javascript') http_response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) http_response['Access-Control-Expose-Headers'] = "Content-Disposition"
In angular:
// component.ts // getFileName not necessary, you can just set this as a string if you wish getFileName(response: HttpResponse<Blob>) { let filename: string; try { const contentDisposition: string = response.headers.get('content-disposition'); const r = /(?:filename=")(.+)(?:")/ filename = r.exec(contentDisposition)[1]; } catch (e) { filename = 'myfile.txt' } return filename } downloadFile() { this._fileService.downloadFile(this.file.uuid) .subscribe( (response: HttpResponse<Blob>) => { let filename: string = this.getFileName(response) let binaryData = []; binaryData.push(response.body); let downloadLink = document.createElement('a'); downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: 'blob' })); downloadLink.setAttribute('download', filename); document.body.appendChild(downloadLink); downloadLink.click(); } ) } // service.ts downloadFile(uuid: string) { return this._http.get<Blob>(`${environment.apiUrl}/api/v1/file/${uuid}/package/`, { observe: 'response', responseType: 'blob' as 'json' }) }
Comments
Post a Comment