I've got code that reads a local folder, then zips up relevant files and uploads them to a server:
var dirEntry = fileSystem.createReader();
dirEntry.readEntries(
function (entries) {
if (entries.length === 0)
return;
var options = new FileUploadOptions();
/* Details omitted */
var zip = new JSZip();
// Map function from Ramda library
R.map(function (entry) {
var fileName = entry.name;
// Check that this is a file, and it's not a zip file.
if (entry.isFile && (fileName.indexOf(".zip", fileName.length - 4) == -1)) {
return entry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (evt) {
// Add the file to the Zip
zip.file(fileName, evt.target.result);
};
reader.readAsArrayBuffer(file);
}, function (error) { // ignore });
}
return null;
}, entries);
fileSystem.getFile(options.fileName, { create: true, exclusive: false },
function (fileEntry) {
fileEntry.createWriter(function (writer) {
// Generate the binary Zip file
var content = zip.generate({ type: "blob", compression: "DEFLATE" });
// Upload the file after it's persisted to storage
writer.onwriteend = function (evt) {
var ft = new FileTransfer();
ft.upload(fileEntry.nativeURL,
UPLOAD_SERVER_URL,
function (data) { // Ignore },
function (error) { // Ignore },
options)
};
// Persist the zip file to storage
writer.write(content);
}, function (error) {
// Ignore
});
}, function (error) {
// Ignore
});
}
, errorFunction);
The problem is that sometimes an empty file is uploaded, which should never happen. So it's probably a synchronization issue that's causing the file to upload before the Zip file is created and written to storage. I'm not sure where the problem is though. I've tried returning Promises from the Map function, then using the Promise.all(...).then() pattern but sometimes I still get a blank file. So either my implementation was incorrect, or zip.generate() also runs asynchronously (or both).
How can I ensure that the zip file is fully written to storage before attempting to upload it?