I devised the following plan:
// Primary Function to Follow
// Capture necessary local data
// Transform into required editable format
// Iterate through user's local images
// Append image names to converted data
// Convert IMAGE to base64 and insert result into zip file
that.uriToBase64(imageFilePath).then((result) => {
console.log("image as base64: ", result);
zip.file(arrayItem2.name, result, {base64: true});
});
// Re-transform data for saving it
// Incorporate data into zip file
// Generate and preserve zip file in user's local storage
// Function uriToBase64()
The Issue at Hand
There seems to be a timing discrepancy with the step 'Incorporate data into zip file' occurring before images actually get added. Despite using .then within the 'Convert IMAGE to base64' step, everything inside seems to execute after overall completion. Consequently, my zip file is being saved without the essential images. Various attempts using async/await syntax have failed to rectify this problem, specifically ensuring the image data gets included inside the zip file during each iteration.
Considering the Promise returned by the uriToBase64() function, employing .then to receive the data should ideally "pause" the loop until the data is successfully added via the zip.file() command, followed by iteration to the next image. Is this not the case? And if so, what would be the correct method of waiting for this outcome, keeping in mind the current algorithm structure?
Resolution Attempts
First Attempt
To address this issue, I attempted to make numerous adjustments, yet success eluded me once more. Updated Algorithm:
// Main Function
// Get some local data
// Convert to some format I need and add to a global variable
// Loop through user's local images
// Add +1 to new global variable 'imageCounter'
// Edit the converted data (now in global variable) to add the image's names to it
// Convert IMAGE to base64 and add result into zip file
that.uriToBase64(imageFilePath).then((result) => {
console.log("image as base64: ", result);
zip.file(arrayItem2.name, result, {base64: true});
that.prepareForWrite();
// Check if this is the last iteration and run function again.
if (thisIsLastIteration == true) { that.prepareForWrite(); }
});
//prepareForWrite() function
// imageCounter - 1
// if imageCounter < 1
// Convert data again to save it
// Add data to zip file
// Generate zip file and save in user's local storage
//uriToBase64() function
In this manner, all received data appears accurate, yet "Generate zip file and save it in user’s local storage" merely includes the first image, ultimately corrupting the file. Second Attempt
Mentioned earlier, my efforts with async/await proved futile. The entire function was divided into smaller functions, with async/await attempted on specific segments needing precedence. My latest use of async/await looked akin to this:
// async Main Function
// Get some local data
// Convert to some format I need to edit
// Iterate through user's local images
// Edit the converted data to add the image's names to it
// Convert IMAGE to base64 and add result into zip file
let result = await that.uriToBase64(imageFilePath);
console.log(result);
zip.file(arrayItem2.name, result, {base64: true});
// Convert data again to save it
// Add data to zip file
// Generate zip file and save it in user's local storage
//uriToBase64() function
Third Attempt
After conducting various tests, receiving data synchronously from the uriToBase64() function propelled me onto distinct paths. Irrespective of obtaining base64 strings, upon generating the ZIP file, only one zipped and corrupted image persisted alongside the other images and primary file being neglected. This realization led me to consider the file zipping process before ZIP file creation. Consequently, I explored solutions to uncover answers. A function present in the JSZIP library seemed promising, allowing scrutiny of content added to the ZIP file. Pursuing relevant inquiries directed me towards this discovery here. The implementation undertaken:
mainFunction() {
let string64 = 'veryLongBase64String';
let b64s = [];
let arrayOfPromises = [];
b64s.push(string64);
b64s.push(string64);
console.log(b64s);
b64s.forEach((b64, index) => {
let fileName = index + ".jpg";
arrayOfPromises.push(this.addFileToZip(fileName, b64));
});
Promise.all(arrayOfPromises)
.then(this.zip.generateAsync({type:"blob"})
.then((content) => {
let filePath = this.file.externalRootDirectory + '/app_downloads/';
this.file.writeFile(filePath, "testZip.zip", content).then(() => {
alert("File saved!");
})
.catch((err) => {
alert("Error while creating file: " + JSON.stringify(err));
});
})
);
}
addFileToZip(name: string, b64: string): Promise<string> {
this.zip.file(name, b64, {base64: true});
return this.zip.file(name).async("uint8array");
}