离子6-电容器文件系统 - 从zip复制sqlite文件

发布于 2025-02-13 03:25:53 字数 2807 浏览 1 评论 0原文

大家好,感谢您抽出宝贵的时间阅读和回答。

描述

我使用离子6 Angular 14 电容器。我需要复制用户上传的zip文件的内容(其中包含 .sqlite文件),然后将其存储在文档文件夹中。为此,我正在使用 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)
    });
  }

一切都很好。当我尝试使用文件系统插件(电容器)将其存储在文档文件夹中时,就会出现问题。

  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的终端引发了此错误:

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

我尝试了文件插件(Awasome-cordova-file),但它不起作用。

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

它引发了下一个错误:

[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}}}

经过测试的解决方案,

  1. 我尝试将zip文件读为arraybuffer或blob ,但是 文件系统插件只能使用字符串数据,因此它不起作用。
  2. 我还尝试更改文件系统的编码值为UTF-8, UTF-16和ASCII,但它不起作用。默认值是base64 编码。
  3. 我尝试使用Cordoba文件插件。在以前的应用程序版本中 很好,所以我尝试(当应用使用Cordoba代替电容器时)。不起作用。

理论

  1. 我不确定这里发生了什么,但似乎比可能与之相关的事情 用编码。我想未设计文件系统4副本.sqlite文件。
  2. 也许与相对路径有关,但我不这么认为。
  3. 您知道的一些Apple sh*t

注意

  1. ...我只需要它在iOS和电子平台中工作即可。浏览器可能是一个加号,但不需要。
  2. 我知道API/REST方法可能会更好,但对于此应用程序不适合。 我们需要存储本地数据。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盗琴音 2025-02-20 03:25:53

好的。几天后,我终于找到了解决方案。这就是它,如果它可以帮助任何人...

我通过在以下片段中看到的“ 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);
    });
  }

我创建了一个看起来像这样的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);
  })

而且有效!请注意,我替换了文件名,因为我需要以这种格式使用另一个插件=)

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:

  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:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文