Search code examples
imagecordovaexpressbinary-datafileapi

Cordova/Phonegap How to write a PNG file to Filesystem?


This question goes for mp3 and wav files as well.

I have set up an express.js server which basically sends the required files as follows:

res.sendFile('someImage.png', {root: './images'});

Then on the client-side, I receive the image with:

var req = new XMLHttpRequest();
...
req.onreadystatechange = function(e) {
    if(req.readyState != 4) return;
    ...
    writeMyFile(null, e.target.response, someCallback);
}
...

So in the response I do have my file. I want to write this file in to my local filesystem. I implement write as follows:

var writeMyFile = function(err, file, someCallback) {
    this.dir.getFile('myImages/someImage.png', {create: true}, function(fileEntry) {
        fileEntry.createWriter(function(fileWriter) {
             var blob = new Blob([file], {type: 'image/png'});
             fileWriter.write(blob);
        }, someCallback);
    }, someCallback);
};

After executing these, I see a png file is created in myImages folder. It is however twice the size of the original file, and it is considered as corrupted by the operating system. Preview cannot view the image. Same goes for mp3/wav files as well, they are twice the size and won't play on any players and etc..

What am I doing wrong here? How can I write those files into filesystem appropiately?

The code above works perfectly when files are json objects. We suspect there might be an encoding problem, but no idea for fixes so far.

Finally, I am using the closure compiler.

Thanks for your help.


Solution

  • After sleeping on the problem, I found out the solution which was incredibly simple. So here it is for future reference.

    On Xhr Request, make sure to set the responseType to arrayBuffer or blob before sending the request. In my case it is arrayBuffer because I already had a blob builder which would act on the data received. That is:

    ...
    req.responseType = 'arraybuffer';
    req.onreadystatechange = ...
    req.send();
    

    It turns out that Mime Type in blob construction won't affect these binary files to be written. In my case, I could store mp3 songs perfectly where I had their MIME as: 'image/png'. However I am not sure if this has other implications, I am just simply saying that the files worked ok no matter which type I had set.