Вы более или менее на правильном пути.Минимальная модификация, которую я могу предложить, чтобы заставить ваш код работать, - это добавить еще одну строку к getFileTemplate
:
getFileTemplate(): any {
this.productService.getFile().subscribe((response) => {
const fileContent = response;
// An application or a document that must be opened in an application
const blob = new Blob([fileContent], { type: 'application/octet-stream' });
if (window.navigator.msSaveBlob) {
// to download in IE
window.navigator.msSaveBlob(blob, 'abcd.csv');
} else {
this.fileUrl= this.sanitizer.bypassSecurityTrustResourceUrl(window.URL.createObjectURL(blob));
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = 'abcd.csv';
document.body.appendChild(a); //<-- Need to add the link to the DOM
a.click();
}
});
}
Конечно, хотя это работает, это не очень чистое решение.Например, пользователь сможет увидеть только что добавленную ссылку.С другой стороны, документация Angular предлагает избегать прямых манипуляций DOM, используя вместо этого Renderer2
.
Вот пример StackBlitz с учетом обеих этих вещей.
В этом примере создается отдельный компонент Downloader
, который действует как базовый элемент привязки, но инкапсулирует логику для запуска загрузки.Затем вы можете использовать этот компонент везде, где хотите запустить загрузку файла.
Суть ответа заключается в следующем фрагменте:
...
constructor(
private element: ElementRef,
private renderer: Renderer2
) {}
...
download(data: Blob, filename: string) {
if(!data) {
return;
}
//Create the anchor element
const link: any = this.renderer.createElement('a');
//Create the URL
const url: any = URL.createObjectURL(data);
//Set the attributes for the anchor
this.renderer.setProperty(link, 'href', url);
this.renderer.setProperty(link, 'download', filename);
//Ensure that the anchor will be hidden, both visibly and from screen readers
this.renderer.setStyle(link, 'display', 'none');
//Add the anchor element to the DOM
this.renderer.appendChild(this.element.nativeElement, link);
//Trigger click on the anchor element to trigger the download
link.click();
//Cleanup by removing the element and revoking the URL.
this.renderer.removeChild(this.element.nativeElement, link);
URL.revokeObjectURL(url);
//Note: This is just a basic example, which does do DOM manipulation
//on every download. You could, instead, append the element in OnInit,
//adjusting its attributes when a download is triggered, and then
//remove the element in OnDestroy.
}