Search code examples
javascriptjsonasynchronousbase64stringify

Synchronously convert Blob to base64 string in Javascript


The only way I found to base64 encode a data Blob to put it in a JSON string, is to use the asyncronous readAsDataUrl() function.

var reader = new window.FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
    base64data = reader.result;                
    console.log(base64data );
}

My problem is that I have to use a synchronous replacer function for JSON.stringify(object, replacer) to tell it how to seriealize Blobs.

var replacer = function (key, value) {
    if (value instanceof Blob) {
        return blobToBase64(value);
    }
    return value;
}

How can I combine those two (asyncronous and synchronous) methods?

Is there a better way to base64 encode those data synchronously?


Solution

  • There should be a synchronious API for reading files - FileReaderSync. The documentation for it states the folowing:

    8.6 Reading on Threads

    Web Workers allow for the use of synchronous File or Blob read APIs, since such reads
    on threads do not block the main thread. This section defines a synchronous API,
    which can be used within Workers [Web Workers].
    Workers can avail of both the asynchronous API (the FileReader object) and the synchronous API
    (the FileReaderSync object).

    The documentation for the Web Workers is available via the link in the quotation above. Altough I'm not familiar with the Web Workers API, the mentioned documentation offers well formated simple examples which create the impression of a intuitive enough API to start using it fast.

    I've not tested this but here is how I would have rewriten your snipet of code:

    var jsonfyObjectWhichMightBeABlob = function(obj){
        var worker = new Worker('jsonfyBlobSynchroniously.js');
        worker.onmessage = function (event) {
            return event.data;
            //or do something with event.data wich should contain the JSON string
        };
        worker.postMessage(obj);
    };  
    

    The jsonfyBlobSynchroniously.js should contain the folowing:

    onmessage = function (event) {
        var replacer = function(key,value){
            if(value instanceof Blob){
                var reader = new window.FileReaderSync();
                return reader.readAsDataURL(value);
            }else{
                return value;
            }
        }
        postMessage( JSON.stringify(event.data,replacer) );
    };