如何在 Ionic4 Angular 中使用 Capacitor 保存下载的文件?

Dea*_*ool 5 typescript ionic-framework ionic4 capacitor

我最近发布了我的 Ionic 4 Angular 应用程序作为网络应用程序和原生 Android 应用程序。
在原生 Android 应用程序中,除了保存下载的文件外,一切正常。

为了下载和保存文件,我一直使用file-savernpm 包如下(这是一个共享服务,每次我必须下载某些东西,从 PDF 到图像等...):

import { saveAs } from 'file-saver';

// ...

saveGenericFile(api: string, fileinfos: any, idFile: string): any {
    let mediaType = 'application/pdf';
    let fileName = '';

    if (fileinfos != null) {
      mediaType = fileinfos.contentType;
      fileName = fileinfos.fileName;
    }

    const headers = this.base.commonHeader;
    const url = this.baseUrl + api + '?id=' + idFile;
    this.http.post(url, null, { headers, responseType: 'blob' }).subscribe(
      (response) => {
        // tslint:disable-next-line: prefer-const
        let blob = new Blob([response], { type: mediaType });
        saveAs(blob, fileName);
      }, e => {
        console.error(e);
        this.toastsvc.generateToast('ERROR! An error occurred while saving this File, try later or contact support', 'danger');
      }, () => {
        /* do nothing */
      }
    );
  }
Run Code Online (Sandbox Code Playgroud)

正如我上面所说,这个代码片段工作正常,但就在我必须从网络版本中保存一些东西的时候。

我能找到的唯一在线示例都是关于 Cordova 和/或以前/不推荐使用的版本。
关于电容器,我刚刚找到了这个文档,从中我找到了这个代码片段:

import { Plugins, FilesystemDirectory, FilesystemEncoding } from '@capacitor/core';

const { Filesystem } = Plugins;

fileWrite() {
  try {
    Filesystem.writeFile({
      path: 'secrets/text.txt',
      data: "This is a test",
      directory: FilesystemDirectory.Documents,
      encoding: FilesystemEncoding.UTF8
    });
  } catch(e) {
    console.error('Unable to write file', e);
  }
}
Run Code Online (Sandbox Code Playgroud)

但问题是我上面的函数返回一个 blob,而这个函数只接受一个字符串作为数据。

那么,在作为 Web 应用程序运行和作为 Android 本机应用程序运行时是否有任何 Capacitor-Native 等效功能可用于下载(和保存)Blob 文件?


更新

我也尝试了以下方法,但它不起作用:

saveGenericFile(api: string, fileinfos: any, gidFile: string): any {
    let mediaType = 'application/pdf';
    let fileName = '';

    if (fileinfos != null) {
      mediaType = fileinfos.contentType;
      fileName = fileinfos.fileName;
    }

    const headers = this.base.commonHeader;
    const url = this.baseUrl + api + '?id=' + gidFile;
    this.http.post(url, null, { headers, responseType: 'blob' }).subscribe(
      (response) => {
        if (!this.useCordovaDl) {
          // tslint:disable-next-line: prefer-const
          let blob = new Blob([response], { type: mediaType });
          saveAs(blob, fileName);
        } else {
          this.blobFileWrite(fileName, response);
        }
      }, e => {
        console.error(e);
        this.toastsvc.generateToast('ERROR! An error occurred while saving this File, try later or contact support', 'danger');
      }, () => {
        /* do nothing */
      }
    );
  }

  blobFileWrite(filename: string, blobfile: Blob) {
    const reader = new FileReader();

    // This fires after the blob has been read/loaded.
    reader.addEventListener('loadend', (e: any) => {
      const text = e.srcElement.result;
      this.fileWrite(filename, text);
    });

    // Start reading the blob as text.
    reader.readAsText(blobfile);
  }

  fileWrite(filename: string, filedata: string) {
    try {
      Filesystem.writeFile({
        path: filename,
        data: filedata
        // ,
        // directory: FilesystemDirectory.Documents,
        // encoding: FilesystemEncoding.UTF8
      });
    } catch (e) {
      console.error('Unable to write file', e);
    }
  }
Run Code Online (Sandbox Code Playgroud)

更新 #2

GitHub 上似乎仍有一个关于使用 Capacitor 保存 Blob 数据的未决问题。同时,我将寻找 Cordova 解决方案。或者,如果平台是 android 或 ios,我将简单地禁用每个下载按钮。
如果我能找到一个,我会在这里发布所有可用的 Cordova 解决方法

par*_*tkr 1

您可以创建一个插件,向其传递一个 URL,它就会本地下载。正如您已经发现的那样,传递 blob/文件是不可能的。

如果没有可用的插件或者您不想创建插件。您可以调用本机函数,从中js可以监听nativeURL 等内容。

  • 嗨@DanyY,抱歉,如果我迟到了,但这几个月我并没有经常使用它。顺便说一句,不幸的是我去年换了工作,我无法再访问我的旧项目了。如果我没记错的话,我在服务器端使用 GET 来返回要下载的文件,在客户端我只是使用了 `window.open('返回文件的 api url' + fileId, '_blank');`应在新窗口中打开文件的“_blank”重载。我不记得我是否使用了默认窗口或者是否从 cordova 导入了它。抱歉,但我希望这可以对您有所帮助,如果有效请告诉我 (2认同)