Set File Name while downloading via blob in Angular 5
Solution 1
You can set the download attribute to the filename you want, set the href to the object url, and then just call click
var blob = new Blob([data], { type: type.toString() });
var url = window.URL.createObjectURL(blob);
var anchor = document.createElement("a");
anchor.download = "myfile.txt";
anchor.href = url;
anchor.click();
Solution 2
If you want the exact filename of the uploaded file, set a custom header of the filename from backed API stream.
You can use it like this: my Excel API response headers:
content-disposition: inline;filename="salesReport.xls"
content-type: application/octet-stream
date: Wed, 22 Aug 2018 06:47:28 GMT
expires: 0
file-name: salesReport.xls
pragma: no-cache
transfer-encoding: chunked
x-application-context: application:8080
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
Service.ts
excel(data: any) {
return this.httpClient.post(this.config.domain +
`/api/registration/excel/download`,data, {observe: 'response', responseType: 'blob'})
.map((res) => {
let data = {
image: new Blob([res.body], {type: res.headers.get('Content-Type')}),
filename: res.headers.get('File-Name')
}
return data ;
}).catch((err) => {
return Observable.throw(err);
});
}
Component.ts
excelDownload (data) {
this.registration.excel(data).subscribe(
(res) => {
const element = document.createElement('a');
element.href = URL.createObjectURL(res.image);
element.download = res.filename;
document.body.appendChild(element);
element.click();
this.toastr.success("Excel generated successfully");
},
(error) =>{
this.toastr.error('Data Not Found');
});
}
Solution 3
Since some asked for a version with promise so you can use await und async:
Part 1: Get the Blob From the server:
generateSapExcel(data: GenerateSapExport): Promise<HttpResponse<Blob>> {
return this.http.post(`${this.pathprefix}/GenerateSapExcel`, data, { responseType: 'blob', observe: 'response' })
.toPromise()
.catch((error) => this.handleError(error));
}
Part 2: Extract HttpResponse and deliver it to the user:
public downloadFile(data: HttpResponse<Blob>) {
const contentDisposition = data.headers.get('content-disposition');
const filename = this.getFilenameFromContentDisposition(contentDisposition);
const blob = data.body;
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.download = filename;
anchor.href = url;
anchor.click();
}
private getFilenameFromContentDisposition(contentDisposition: string): string {
const regex = /filename=(?<filename>[^,;]+);/g;
const match = regex.exec(contentDisposition);
const filename = match.groups.filename;
return filename;
}
Part 3: Combine both:
const blobresponse = await this.dataService.generateSapExcel(dataToSend);
this.downloadService.downloadFile(blobresponse);
Part 4: server:
[HttpPost]
[Route(nameof(GenerateSapExcel))]
public async Task<FileStreamResult> GenerateSapExcel(GenerateSapExportDto dto)
{
Stream stream = await _sapKurepoService.GenerateSapExcel(dto);
FileStreamResult result = File(stream, FileHelper.ContentypeExcel, "excel.xlsx");
return result;
}
Tanwer
Updated on March 28, 2020Comments
-
Tanwer about 4 years
Below is my Typescript code to download file From API
DownloadLM() { var ID= sessionStorage.getItem("UserID"); return this.http.get(this.baseurl + 'api/DownloadFiles/DownloadLM/' + ID, { headers: { 'Content-Type': 'application/json' }, responseType: 'arraybuffer' } ) .subscribe(respData => { this.downLoad(respData, this.type); }, error => { }); } downLoad(data: any, type: string) { var blob = new Blob([data], { type: type.toString() }); var url = window.URL.createObjectURL(blob); var pwa = window.open(url); if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') { alert('Please disable your Pop-up blocker and try again.'); } }
This is Fine to download Excel File , but it gives a random name to file which I don't want , I want to set file name of my choice when downloading it ,
Where can I set file name here ? any property of Blob ?
-
Tanwer over 5 yearsThanks , it works but I am also checking if pop up is blocked in browser or not , for that I wrote var pwa = anchor.click(); if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') { alert('Please disable your Pop-up blocker and try again.'); } , but in your code it is not possible to check it as anchor.click() does not return a window
-
Sajeetharan over 5 yearsyou might need to do a hack there, upvote if this helped
-
Tanwer over 5 yearsas it is happening in JS based framework and JS can be disabled , so taking caring of that is also required (pop up enable message), It partly helped not fully
-
Saravanan Sachi over 5 yearsAs it throws "Property 'download' does not exist on type HtmlAnchorElement" setting it as anchor.setAttribute("download", "<fileName>"); works
-
yonexbat over 4 yearsres.headers.get('File-Name') helped. tnx.