Question

I have the following code to write an image into the filesystem, and read it back for display. Prior to trying out the filesystem API, I loaded the whole base64 image into the src attribute and the image displayed fine. Problem is the images can be large so if you add a few 5MB images, you run out of memory. So I thought I'd just write them to the tmp storage and only pass the URL into the src attribute. Trouble is, nothing gets displayed.

Initially I thought it might be something wrong with the URL, but then I went into the filesystem directory, found the image it was referring to and physically replaced it with the real binary image and renamed it to the same as the replaced image. This worked fine and the image is displayed correctly, so the URL looks good.

The only conclusion I can come to is that the writing of the image is somehow wrong - particularly the point where the blob is created. I've looked through the blob API and can't see anything that I may have missed, however I'm obviously doing something wrong because it seems to be working for everyone else.

As an aside, I also tried to store the image in IndexedDB and use the createObjectURL to display the image - again, although the URL looks correct, nothing is displayed on the screen. Hence the attempt at the filesystem API. The blob creation is identical in both cases, with the same data.

The source data is a base64 encoded string as I mentioned. Yes, I did also try to store the raw base64 data in the blob (with and without the prefix) and that didn't work either.

Other info - chrome version 28, on linux Ubuntu


    //strip the base64 `enter code here`stuff ...
    var regex = /^data.+;base64,/;
    if (regex.test(imgobj)) {   //its base64
        imgobj = imgobj.replace(regex,"");
        //imgobj = B64.decode(imgobj);
        imgobj = window.atob(imgobj);
    } else {
        console.log("it's already :", typeof imgobj);
    }

    // store the object into the tmp space
    window.requestFileSystem(window.TEMPORARY, 10*1024*1024, function(fs) {
        // check if the file already exists
        fs.root.getFile(imagename, {create: false}, function(fileEntry) {
            console.log("File exists: ", fileEntry);
            callback(fileEntry.toURL(), fileEntry.name);
                        //
        }, function (e) {   //file doesn't exist
            fs.root.getFile(imagename, {create: true}, function (fe) {
                console.log("file is: ", fe);
                fe.createWriter(function(fw){
                    fw.onwriteend = function(e) {
                        console.log("write complete: ", e);
                        console.log("size of file: ", e.total)
                        callback(fe.toURL(), fe.name);
                    };
                    fw.onerror = function(e) {
                        console.log("Write failed: ", e.toString());
                    };
                    var data = new Blob([imgobj], {type: "image/png"});
                    fw.write(data);
                }, fsErrorHandler);
            }, fsErrorHandler);
        });
        // now create a file
    }, fsErrorHandler);

Output from the callback is:

<img class="imgx" src="filesystem:file:///temporary/closed-padlock.png" width="270px" height="270px" id="img1" data-imgname="closed-padlock.png">

I'm at a bit of a standstill unless someone can provide some guidance...

UPDATE

I ran a test to encode and decode the base64 image with both the B64encoder/decoder and atob/btoa -

console.log(imgobj); // this is the original base64 file from the canvas.toDataURL function
/* B64 is broken*/
B64imgobjdecode = B64.decode(imgobj);
B64imgobjencode = B64.encode(B64imgobjdecode);
console.log(B64imgobjencode);
/* atob and btoa decodes and encodes correctly*/
atobimgobj = window.atob(imgobj);
btoaimgobj = window.btoa(atobimgobj);
console.log(btoaimgobj);

The results show that the btoa/atob functions work correctly but the B64 does not - probably because the original encoding didn't use the B64.encode function...

The resulting file in filesystem TEMPORARY, I ran through an online base64 encoder for comparison and the results are totally different. So the question is - while in the filesystem temp storage, is the image supposed to be an exact image, or is it padded with 'something' which only the filesystem API understands? Remember I put the original PNG in the file system directory and the image displayed correctly, which tends to indicate that the meta-data about the image (eg. the filename) is held elsewhere...

Can someone who has a working implementation of this confirm if the images are stored as images in the filesystem, or are padded with additional meta-data?

Was it helpful?

Solution

So to answer my own question - the core problem was in the base64 encoding/decoding - I've since then changed this to use things like ajax and responseTypes like arraybuffer and blob and things have started working. To answer the last part of the question, this is what I've found - in the filesystem tmp storage, yes the file is supposed to be an exact binary copy - verified this in chrome and phonegap.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top