Hello everyone and thanks for taking time to read and answer.
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}}}
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 =)