Angular/Javascript - ссылка на загрузку файла не работает на мобильных устройствах
У меня есть ссылка на ссылку для загрузки шаблона из моего приложения. Он отлично работает в Chrome и IE, но не работает на мобильных устройствах ( Android и iPhone)
У меня есть эта функция, которая вызывается, нажав на ссылку..
fileUrl: any;
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';
a.click();
}
});
}
И в файле HTML
`<a href="javascript:void(null)"
(click)="getFileTemplate();"
id="link-inline-excel"
class="u-text--document u-text--document-link"
download="abcd.csv"><span>Title my file (7MB)</span></a>`
Это не работает в мобильных устройствах. Я что-то здесь упускаю?
1 ответ
Вы более или менее на правильном пути. Минимальная модификация, которую я могу предложить, чтобы заставить ваш код работать, - это добавить еще одну строку в 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.
}