Sending file as data in jquery ajax

Recently I was working on a project where I needed to upload a file in a single page application, so form submission to a backend file was out of the question.

_config.yml

There is also option of uploading files directly with ajax but the backend guy asked me if I can send files in Base64 format.

I knew I can convert image into Base64 by loading it in canvas this way.

Read more on canvas .

    var img = new Image();
    img.src = src; //image to be converted
    var canvas = document.createElement('CANVAS');
    var ctx = canvas.getContext('2d');
    var dataURL;
    canvas.height = img.height;
    canvas.width = img.width;
    ctx.drawImage(img, 0, 0);
    dataURL = canvas.toDataURL();
    console.log(dataUrl); //log Base64 image string
 

But the issue here is that image takes some time to load, resulting in the wrong Base64 string. Fortunately, we have an event for image load completion which we can use to ensure that our image has completely loaded before we draw it into canvas.

The changed code.

    var img = new Image();
    img.onload = function() {
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL();
        console.log(dataURL);
    };
    img.src = src;
 

Finally decided to convert the code into a generic function that can be invoked any time to do the conversion for us.

    function toDataUrl(src, callback) {
 	    var img = new Image();
 	    img.crossOrigin = 'Anonymous';
 	    img.onload = function() {
 		    var canvas = document.createElement('CANVAS');
 		    var ctx = canvas.getContext('2d');
 		    var dataURL;
 		    canvas.height = this.height;
 		    canvas.width = this.width;
 		    ctx.drawImage(this, 0, 0);
 		    dataURL = canvas.toDataURL();
 		    callback(dataURL);
 	    };

 	    img.src = src;
 	    if (img.complete || img.complete === undefined) {
 		    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
 		    img.src = src;
 	    }
    }
 

We can use it this way.

    toDataUrl('image/url', function(base64Img) {
 	    console.log(base64Img);
    });
 

Also I added a check in function to make sure the load event fires for cached images too.

    if (img.complete || img.complete === undefined) {
        img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
        img.src = src;
    }
 

Later I found out that we can also use FileReader API to read the file and convert into the Base64 format.

Read more on FileReader API.

We can then send the image we converted in any ajax request.

Written on June 8, 2016