ank5
asked on
upload zip file from Ionic to NodeJS
From my Ionic app, running on iPad, I need to upload a zip file to Node Express.
Below is my code for saving the zip on iPad and posting it to the Express server
This function is then called from the controller. Upon zip file creation it sends it to the Node server using $cordovaFileTransfer.
On the Node server side, below code is saving the zip file
This code creates a corrupted zip file when called from ionic app. However, if I attach a file in Postman and post to this URL then a valid zip file is created.
So, I suspect it could be something to do with how I am creating my zip file on Ionic (as a blob) and seems that node code is not able to understand that.
In nutshell, zip being created in the device is valid (as I am able to open it) and the zip saved on the node server is also valid when called from Postman. However, when zip created in ionic is send to node, then node saves a corrupted zip file.
Is there something else that I need to be doing on either the node or the ionic side to make it work.
Below is my code for saving the zip on iPad and posting it to the Express server
//This creates the zip file locally. Zip creation on iPad works fine as I am able to open it.
//Using JSZip to create a zip file. Type is set to blob
var zipFiles = function(filesList, uniqueFilename) {
var zip = new JSZip();
var zipFilesPromises = filesList.map(function (file) {
return $cordovaFile.readAsBinaryString(cordova.file.dataDirectory + $rootScope.username, file)
.then(function (binaryData) {
return zip.file(file, binaryData, { binary: true });
});
});
return Promise.all(zipFilesPromises)
.then(function () {
return zip.generateAsync({ type: "blob" });
})
.then(function (blob) {
return $cordovaFile.writeFile(cordova.file.dataDirectory + $rootScope.username, uniqueFilename, blob, true);
})
.then(function (data) {
return Promise.resolve(data);
})
.catch(function (error) {
console.log('Error while zipping and writing ' + JSON.stringify(error));
})
}
This function is then called from the controller. Upon zip file creation it sends it to the Node server using $cordovaFileTransfer.
return fileAPI.zipFiles(docList, zipFilename)
}).then(function(data) {
var targetPath = cordova.file.dataDirectory + $rootScope.username+ '/'+zipFilename;
var trustHosts = true;
var options = {};
var server = config.nodeServerEndpoint + '/uploadparcel';
return $cordovaFileTransfer.upload(server, targetPath, options, trustHosts);
}).then(function (result) {
console.log("success", result);
}).catch(function(error) {
console.log('Error - '+JSON.stringify(error));
});
On the Node server side, below code is saving the zip file
function uploadZip(request, response) {
var size = 0;
var data = new Buffer('');
request.on('data', function (chunk) {
data = Buffer.concat([data, chunk]);
});
request.on('end', function () {
request.rawBody = data;
fs.writeFile('userdata/abc123.zip', request.rawBody, 'binary', function(err){
if (err) {
throw err;
}
})
response.end("Thanks");
});
request.on('error', function(e) {
console.log("ERROR ERROR: " + e.message);
});
}
This code creates a corrupted zip file when called from ionic app. However, if I attach a file in Postman and post to this URL then a valid zip file is created.
So, I suspect it could be something to do with how I am creating my zip file on Ionic (as a blob) and seems that node code is not able to understand that.
In nutshell, zip being created in the device is valid (as I am able to open it) and the zip saved on the node server is also valid when called from Postman. However, when zip created in ionic is send to node, then node saves a corrupted zip file.
Is there something else that I need to be doing on either the node or the ionic side to make it work.
If you compare the two files - does this shed any light?
ASKER
When I try to unzip the file created on node (though Ionic), it gives the following message
Also, it's much smaller in size than the file that is created on Node through Postman.
unzip userdata/abc123.zip
Archive: userdata/abc123.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of userdata/abc123.zip or
userdata/abc123.zip.zip, and cannot find userdata/abc123.zip.ZIP, period.
Also, it's much smaller in size than the file that is created on Node through Postman.
I would do a binary compare of the two files to see what is different - it might give some clue as to what / how the file is being corrupted.
ASKER
You are right, binary comparison helped. But still don't know how to resolve the problem.
It seems that $cordovaFileTransfer plugin is adding some bytes to the zip file. When I try to unzip the file which is uploaded by $cordovaFileTransfer plugin, it gives me an error message stating
Then I did a binary comparison of the zip file send through $cordovaFileTransfer (not working) and the one send through postman (working). Found that the one send through $cordovaFileTransfer has the following in the beginning of the zip file (which is making it invalid).
All the content is also there as a part of the (not working) zip, but these additional bytes in the beginning are making it invalid.
Here is my $cordovaFileTransfer code. I guess, it’s options that is causing the problem
In my use case, user does not select the file that needs to be uploaded. Based on a user action (like button click), application would look for a zip file in a specific location on iPad and upload it using $cordovaFileTransfer.
It seems that $cordovaFileTransfer plugin is adding some bytes to the zip file. When I try to unzip the file which is uploaded by $cordovaFileTransfer plugin, it gives me an error message stating
warning[abc.zip]: 172 extra bytes at the beginning or within zip file
Then I did a binary comparison of the zip file send through $cordovaFileTransfer (not working) and the one send through postman (working). Found that the one send through $cordovaFileTransfer has the following in the beginning of the zip file (which is making it invalid).
--+++++org.apache.cordova.formBoundary
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: application/octet-stream
Content-Length: 22705
All the content is also there as a part of the (not working) zip, but these additional bytes in the beginning are making it invalid.
Here is my $cordovaFileTransfer code. I guess, it’s options that is causing the problem
return fileAPI.saveDataInFs(JSON.stringify(uploadJson), jsonFilename)
.then(function(data) {
return fileAPI.zipFiles(docList, zipFilename)
}).then(function(data) {
var targetPath = cordova.file.dataDirectory + $rootScope.username+ '/'+jsonFilename;
var trustHosts = true;
var options = {
mimeType:"application/octet-stream"
};
var server = config.nodeServerEndpoint + '/upload';
return $cordovaFileTransfer.upload(server, targetPath, options, trustHosts);
}).then(function (result) {
console.log("success", result);
}).catch(function(error) {
console.log('Error - '+JSON.stringify(error));
});
In my use case, user does not select the file that needs to be uploaded. Based on a user action (like button click), application would look for a zip file in a specific location on iPad and upload it using $cordovaFileTransfer.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.