FileReader dragging image from browser window

Viewed 1074

I have a div where users can drag and drop an image and then, using FileReader, I get the base64 of the image. Works fine.

dropper.ondrop = function (e) {

    e.preventDefault();

    var file = e.dataTransfer.files[0];

    var reader = new FileReader();
    reader.readAsDataURL(file);
};

My issue is if I have a browser window open and drag and drop an image from the browser I get the error:

Failed to execute 'readAsDataURL' on 'FileReader': 
parameter 1 is not of type 'Blob'.

Now, is there any turnaround to get the base64 of an image dragged from the browser window?

Ultimately, is there is a way to get the image URL and then the actual base64 with a server side curl request?

Any idea?

2 Answers

You can use e.dataTransfer.getData('url') to tell whether there's a URL available. Like this:

var url = e.dataTransfer.getData('url');
if(url){
    console.log('Url');
    console.log(url);
}else{
    console.log('File');
    var file = e.dataTransfer.files[0];
    var reader = new FileReader();
    reader.readAsDataURL(file);
}

Then, having the URL, you can load an img element and use draw it on a canvas to grab the base64 representation. Like this:

var img = document.createElement('img');
img.crossOrigin = 'anonymous';
img.onload = function(){
    var canvas = document.createElement('canvas');
    canvas.width = this.width;
    canvas.height = this.height;
    var context = canvas.getContext('2d');
    context.drawImage(this, 0, 0);
    console.log(canvas.toDataURL());
};
img.src = url;

This would be the "final" product:

var dropper = document.querySelector('div');
dropper.ondragover = function(e) {
    e.preventDefault();
}
dropper.ondrop = function (e) {
    e.preventDefault();
    var url = e.dataTransfer.getData('url');
    if(url){
        console.log('Url');
        console.log(url);
        var img = document.createElement('img');
        img.crossOrigin = 'anonymous';
        img.onload = function(){
            var canvas = document.createElement('canvas');
            canvas.width = this.width;
            canvas.height = this.height;
            var context = canvas.getContext('2d');
            context.drawImage(this, 0, 0);
            console.log(canvas.toDataURL());
        };
        img.src = url;
    }else{
        console.log('File');
        var file = e.dataTransfer.files[0];
        var reader = new FileReader();
        reader.readAsDataURL(file);
    }
};
div{
    border:1px solid red;
    height:240px;
    width:100%;
}
<div>Drop here</div>

Also available here: https://jsfiddle.net/8u6Lprrb/1/

The first parameter comes through with the "http://" or "https://" protocol instead of the expected "file://" protocol. and thats why you cant read it with the HTML5 FILE API, so you may want to download and save the file first before trying to read the contents. on the other hand, you can update an img tag's src attribute with the retrieved url and skip the readDataAsUrl() portion to hotlink the image.

Related