从 api 下载并打开电容器文件

kes*_*hra 1 ionic-framework capacitor

我正在开发带有电容器 5 的 Angular Ionic 7 应用程序。我的应用程序的一页是不同文件的列表(pdf、txt、csv)。用户可以选择一个文件,它应该下载到设备上。我尝试创建一个对象 Url 并使用 window.open(fileURL) 打开它,但没有任何反应,也没有错误。我尝试了带有 downloadFile() Api 的库 @capacitor/filesystem 。结果包含一个 blob,但我无法将其存储在设备上。有人知道怎么做这个吗?

 Filesystem.downloadFile({ path: Directory.Data, url: url, directory: Directory.Data }).then((res) => {
    console.log('download finished');
  });
Run Code Online (Sandbox Code Playgroud)

Rap*_*let 5

我们将使用电容器社区的FileOpener 库。write_blob 库一起使用,它不是必需的,但更快、更可靠。

如何

  1. 下载库
npm install @capacitor-community/file-opener
npm install capacitor-blob-writer
npx cap sync
Run Code Online (Sandbox Code Playgroud)
npm install @capacitor-community/file-opener
npm install capacitor-blob-writer
npx cap sync
Run Code Online (Sandbox Code Playgroud)
// Not required step, just cleaner ;)
export interface CustomFile {
  title: string, 
  url: string, 
  path: string, 
  mineType: string 
}
Run Code Online (Sandbox Code Playgroud)

奖励:文件系统

这段代码大量使用了文件系统,这里有一些小帮助可以指导您

  1. 如何下载
  2. 不要忘记征求许可;)
// 2. Import it into your file (I'm using a services)
import { FileOpener, FileOpenerOptions } from '@capacitor-community/file-opener'
import write_blob from 'capacitor-blob-writer'
import { Directory, Filesystem } from '@capacitor/filesystem'

@Injectable({
  providedIn: 'root',
})
export class OpenLinkService {
  progress = 0 // If you wish to show a loader :)
  downloadingUrls = [] // Avoid downloading multiple time the same asset

  constructor() {}

// 3. We'll be preparing & downloading the file
  private async _downloadAndOpenFiles(file: CustomFile) {
   if(this.downloadingUrls.includes(file.url)) return
   this.downloadingUrls.push(file.url)

    this._httpClient
      .get(url, {
        responseType: 'blob',
        reportProgress: true,
        observe: 'events',
      })
      .subscribe({
        next: async (event) => {
          if (event.type === HttpEventType.DownloadProgress) {
            this.progress = Math.round((100 * event.loaded) / event.total)
          } else if (event.type === HttpEventType.Response) {
            this.progress = 100

            const filePath = await this._getFilePath(file.title, event.body)

            await this._openFileWithType(filePath, file.mineType)
            this.progres = 100
            this.downloadingUrls = this.downloadingUrls.filter((dUrl) => dUrl !== file.url)
          }
        },
        error: (error) => {
          console.error(error)
        },
      })
  }

// 4 Method to retrieve the fiel we've saved
  private async _getFilePath(fileName: string, blob: Blob): Promise<string> {
    const name = fileName

    try {
      // 5. Save the file locally
      return await this._saveBlobFile(blob, name)
    } catch {
      // 6. In case the file did already exists -> we retrieve it
      await Filesystem.getUri({
        path: name,
        directory: Directory.Cache,
      })
        .then((savedFile) => {
          return savedFile.uri
        })
        .catch((error) => {
          console.error(error)
          throw new Error('Cannot save/open the file')
        })
    }
  }

// 5. Save the file locally
  private _saveBlobFile(blob: Blob, fileName: string) {
    return write_blob({
      path: fileName,
      directory: Directory.Cache,
      blob: blob,
    })
  }

// 7. Open the file
  private async _openFileWithType(filePath: string, fileType: string) {
    const fileOpenerOptions: FileOpenerOptions = {
      filePath: filePath,
      contentType: fileType,
    }

    await FileOpener.open(fileOpenerOptions)
      .then(() => {
        // 'File is opened'
      })
      .catch((error) => {
        console.error(error)
      })
  }

//  Bonus: Localhost:4200. A little more code, to make it work even while testing on your laptop ;)
  public async openFile(file: CustomFile) {
    if (!file?.url) return

    try {
      this._downloadAndOpenFiles(file)
    } catch (error) {
      console.error(error)
      Browser.open({ url: file.path })
    }
  }
Run Code Online (Sandbox Code Playgroud)

干杯