javascript - Angular/Javascript - 下载文件链接在移动设备上不起作用
问题描述
我有一个 href 链接可以从我的应用程序中下载模板。它在 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>`
这不适用于移动设备。我在这里错过了什么吗?
解决方案
你或多或少是在正确的轨道上。为了使您的代码正常工作,我可以提供的最小修改是在以下位置再添加一行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.
}
推荐阅读
- python - Auto-py-to-exe 自动运行 cscript.exe
- java - 无法在 Eclipse Java 中找出此错误
- android - 如何在动态功能模块中将 SavedStateHandle 注入 ViewModel?
- java - 使用 Pentaho 中的用户定义 Java 类将 pdf 加载到 S3
- android - 使用分页适配器的嵌套recyclerview(分页3)在滚动后显示错误的图像
- java - 如果我创建一个可以容纳 10 个对象的数组,该数组是否有可能少于 10 个对象?
- docker - 如何找到所有未命名的模块
- excel - 如何使用 InStr 和 Excel Search 搜索文本?
- css - 防止 vuetify 污染全局样式范围
- windows - 如何从外部存档中批量导入变量(例如单词)?