简体   繁体   English

Ionic 6 - 电容器文件系统 - 从 ZIP 复制 SQLite 文件

[英]Ionic 6 - Capacitor Filesystem - copy SQLite files from ZIP

Hello everyone and thanks for taking time to read and answer.大家好,感谢您花时间阅读和回答。

DESCRIPTION描述

I am using Ionic 6 with Angular 14 and capacitor .我正在使用Ionic 6Angular 14电容器 I need to copy the content of an ZIP file uploaded by the user (it contains .sqlite files ), and store it inside the Documents folder.我需要复制用户上传的 ZIP 文件的内容(它包含.sqlite 文件),并将其存储在 Documents 文件夹中。 For that, I'm using JSZip library.为此,我正在使用JSZip库。

  public async unzipFolder(file: File): Promise<string[]> {
    const zip: JSZip = await JSZip.loadAsync(file);
    const promises: Promise<string>[] = [];

    zip.forEach((relativePath: string, zipFile: JSZipObject) =>
        promises.push(this.unzipFile(zipFile));
    );
    return await Promise.all(promises);
  }

  public async unzipFile(compressedFile: JSZipObject): Promise<string> {
    return await compressedFile.async('string').then((data: string) => {
     this.fileOpsService.write(compressedFile.name, data)
    });
  }

Everything works fine here.这里一切正常。 Problems comes when I try to store it in Documents folder using Filesystem plugin (capacitor) .当我尝试使用Filesystem plugin (capacitor)将其存储在 Documents 文件夹中时出现问题。

  public async write(
    path: string,
    data: string,
    directory: Directory = Directory.Documents
  ): Promise<WriteFileResult> {
    return await Filesystem.writeFile({
      path: path,
      directory: directory,
      data: data,
      recursive: false,
    });
  }

XCode's terminal throws this error: XCode 的终端抛出这个错误:

{"errorMessage":"Unable to save file"}

I tried File plugin (awasome-cordova-file) but it does not work.我尝试了文件插件(awasome-cordova-file),但它不起作用。

  public async write(
    path: string,
    data: ArrayBuffer,
    directory: Directory = Directory.Documents
  ): Promise<any> {
    return await File.writeFile(path, '', data, {replace: true})
  }

It throws the next error:它引发下一个错误:

[DocumentManager] Failed to associate thumbnails for picked URL file:///private/var/mobile/Containers/Shared/AppGroup/XXX/File%20Provider%20Storage/TEST_BATCH2.zip with the Inbox copy file:///private/var/mobile/Containers/Data/Application/XXX/tmp/io.ionic.starter.ivan-Inbox/TEST_BATCH2.zip: Error Domain=QLThumbnailErrorDomain Code=102 "(null)" UserInfo={NSUnderlyingError=0x282532cd0 {Error Domain=GSLibraryErrorDomain Code=3 "Generation not found" UserInfo={NSDescription=Generation not found}}}

TESTED SOLUTIONS经过测试的解决方案

  1. I tried to read the ZIP files as ArrayBuffer or Blob , but the Filesystem plugin can only use string data, so it didn't work.我尝试将 ZIP 文件读取为 ArrayBuffer 或 Blob ,但 Filesystem 插件只能使用字符串数据,所以它不起作用。
  2. I also try to change the encoding value of Filesystem to UTF-8, UTF-16 and ASCII but it didn't work.我还尝试将 Filesystem的编码值更改为 UTF-8、UTF-16 和 ASCII,但没有成功。 The default value is Base64 encoding.默认值为 Base64 编码。
  3. I try to use the cordoba File plugin .我尝试使用 cordoba File 插件 In previous app versions this was working fine, so I try it (when the app used cordoba instead capacitor).在以前的应用程序版本中,这工作正常,所以我尝试了一下(当应用程序使用 cordoba 代替电容器时)。 Didn't work.没用。

THEORIES理论

  1. I'm not sure about what is happening here, but seems than could be something related with encoding.我不确定这里发生了什么,但似乎可能与编码有关。 Filesystem is not designed 4 copy .sqlite files I suppose.我想文件系统不是设计的 4 个副本 .sqlite 文件。
  2. Maybe something related with relative paths, but I don't think so.也许与相对路径有关,但我不这么认为。
  3. Some Apple sh*t, u know...一些Apple sh*t,你知道...

Notes笔记

  1. I just need it to work in iOS and Electron platforms.我只需要它在 iOS 和 Electron 平台上工作。 Browser could be a plus, but is not required.浏览器可能是一个加号,但不是必需的。
  2. I know that an API/REST approach could be better, but it's not posible for this app.我知道 API/REST 方法可能会更好,但对于这个应用程序来说是不可行的。 We need to store the data localy.我们需要将数据存储在本地。

Ok.好的。 After a few days, I finally found a solution.几天后,我终于找到了解决方案。 Here is it, if it can help anyone...这是它,如果它可以帮助任何人......

I changed the way of read from ZIP file by replacing 'string' with 'blob' as you can see in the following snippet:我通过将 'string' 替换为 'blob' 更改了从 ZIP 文件中读取的方式,如您在以下代码段中所见:

  public async unzipFile(compressedFile: JSZipObject): Promise<void> {
    return await compressedFile.async('blob').then(async (data: Blob) => {
      const filename: string = compressedFile.name
        .replace('.sqlite', 'SQLite.db');
      const base64 = await this.convertBlobToBase64(data);
      this.fileOpsService.write(filename, base64);
    });
  }

I create a convertBlobToBase64 helper function that looks like this:我创建了一个如下所示的 convertBlobToBase64 辅助函数:

  private convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => {
    const reader: FileReader = new FileReader();
    reader.onerror = reject;
    reader.onload = () => {
      resolve(reader.result);
    }
    reader.readAsDataURL(blob);
  })

And it works!它有效! Note that I replaced the filename because I need it in that format to read it with another plugin =)请注意,我替换了文件名,因为我需要以这种格式使用另一个插件来读取它=)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM