【问题标题】:Angular/Javascript - Download file link is not working on mobile devicesAngular/Javascript - 下载文件链接在移动设备上不起作用
【发布时间】:2019-02-19 10:24:00
【问题描述】:

我有一个 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>`

这不适用于移动设备。 我在这里错过了什么吗?

【问题讨论】:

  • 在触发click之前,您没有将创建的下载链接附加到DOM。
  • @Rikonator:: - 我到底需要怎么做?

标签: javascript angular angular6 mobile-devices


【解决方案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 example 考虑到这两点。

该示例创建了一个单独的Downloader 组件,其作用类似于基本锚元素,但封装了触发下载的逻辑。然后,您可以在要触发文件下载的任何地方使用此组件。

答案的要点是这个sn-p:

...

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.
}

【讨论】:

  • 我尝试添加 document.body.appendChild(a); //
  • 我要做的是在这里angular-ynl3up.stackblitz.io,但它不适用于 iOS 设备
  • 嗨 Rekonator,这在 iOS 设备上仍然不起作用
  • 嘿,您找到解决方案了吗??
猜你喜欢
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多