Angular / Javascript - ссылка на загрузку файла не работает на мобильных устройствах - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть ссылка на ссылку для загрузки шаблона из моего приложения.Он отлично работает в 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 Ответ

0 голосов
/ 19 февраля 2019

Вы более или менее на правильном пути.Минимальная модификация, которую я могу предложить, чтобы заставить ваш код работать, - это добавить еще одну строку к 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.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...