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

atmip9wb  于 2022-12-08  发布在  Ionic
关注(0)|答案(1)|浏览(179)

Hello everyone and thanks for taking time to read and answer.

DESCRIPTION

I am using Ionic 6 with Angular 14 and capacitor. 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. For that, I'm using JSZip library.

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

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:

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

I tried File plugin (awasome-cordova-file) but it does not work.

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.
  2. I also try to change the encoding value of Filesystem to UTF-8, UTF-16 and ASCII but it didn't work. The default value is Base64 encoding.
  3. I try to use the cordoba File plugin. In previous app versions this was working fine, so I try it (when the app used cordoba instead capacitor). 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.
  2. Maybe something related with relative paths, but I don't think so.
  3. Some Apple sh*t, u know...

Notes

  1. I just need it to work in iOS and Electron platforms. 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. We need to store the data localy.
gzszwxb4

gzszwxb41#

好的。过了几天,我终于找到了解决办法。这里是它,如果它能帮助任何人...
我通过用“blob”替换“string”更改了从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);
    });
  }

我创建了一个convertBlobToBase 64辅助函数,如下所示:

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

而且它工作了!请注意,我替换了文件名,因为我需要它的格式来阅读它与另一个插件=)

相关问题