8

I am trying to encode and decode an image. I am using the FileReader's readAsDataURL method to convert the image to base64. Then to convert it back I have tried using readAsBinaryString() and atob() with no luck. Is there another way to persist images without base64 encoding them?

readAsBinaryString()

Starts reading the contents of the specified Blob, which may be a File. When the read operation is finished, the readyState will become DONE, and the onloadend callback, if any, will be called. At that time, the result attribute contains the raw binary data from the file.

Any idea what I'm doing wrong here?

Sample Code http://jsfiddle.net/qL86Z/3/

$("#base64Button").on("click", function () {
    var file = $("#base64File")[0].files[0]
    var reader = new FileReader();

    // callback for readAsDataURL
    reader.onload = function (encodedFile) {
        console.log("reader.onload");
        var base64Image = encodedFile.srcElement.result.split("data:image/jpeg;base64,")[1];
        var blob = new Blob([base64Image],{type:"image/jpeg"});
        var reader2 = new FileReader();

        // callback for readAsBinaryString
        reader2.onloadend = function(decoded) {
            console.log("reader2.onloadend");
            console.log(decoded); // this should contain binary format of the image

            // console.log(URL.createObjectURL(decoded.binary)); // Doesn't work
        };
        reader2.readAsBinaryString(blob);

        // console.log(URL.createObjectURL(atob(base64Image))); // Doesn't work

    };
    reader.readAsDataURL(file);
    console.log(URL.createObjectURL(file)); // Works
});

Thanks!

sissonb
  • 3,730
  • 4
  • 27
  • 54

2 Answers2

14

After some more research I found the answer from here I basically needed to wrap the raw binary in an arraybuffer and convert the binary chars to Unicode.

This is the code that was missing,

    var binaryImg = atob(base64Image);
    var length = binaryImg.length;
    var ab = new ArrayBuffer(length);
    var ua = new Uint8Array(ab);
    for (var i = 0; i < length; i++) {
        ua[i] = binaryImg.charCodeAt(i);
    }

The full sample code is here

sissonb
  • 3,730
  • 4
  • 27
  • 54
1

URL.createObjectURL expects a Blob (which can be a File) as its argument. Not a string. That's why URL.createObjectURL(file) works.

Instead, you are creating a FileReader reader that reads file as a data url, then you use that data url to create another Blob (with the same contents). And then you even create a reader2 to get a binary string from the just constructed blob. However, neither the base64Image url string part (even if btoa-decoded to a larger string) nor the decoded.binary string are vaild arguments to URL.createObjectURL!

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Is it possible to convert `base64Image` back into the original file though? I'm basically trying to undo what `reader.readAsDataURL(file);` does with `readAsBinaryString()` or `atob()`. – sissonb Feb 20 '13 at 00:31
  • `var blob = new Blob([base64Image],{type:"image/jpeg"});` should do it? Try `URL.createObjectURL(blob);` – Bergi Feb 20 '13 at 00:36
  • It shows a broken image for `URL.createObjectURL(blob);` I updated the JSFiddle here, http://jsfiddle.net/qL86Z/7/ Here's a screencast showing the broken image. http://screencast.com/t/vVVGNTvo – sissonb Feb 20 '13 at 00:41