I am working on a website that allows users to edit photos (in-browser) and then upload them. To edit the images in-browser, I use some JavaScript libraries that work with images in base64. As a result, to POST the image to my server, a simple form with a file input cannot be used. The value of a hidden input is set to a base64 string of the edited image, and that is POSTed. Please see the following, short example.
Obviously, this is very much stripped down, but it does contain the problem I'm running into. In POSTing a 3MB animated GIF, it took 6.5 minutes. During which, my puter was almost pletely frozen/unresponsive. (Note: This works perfectly for small images, though)
It might be an OS/browser issue, (latest Google Chrome on Ubuntu) but I doubt it. If I put that file input inside the form, and remove base64-ing of data, (i.e. - a standard POSTing of a file) it goes in about one second.
Compare 6.5 minutes to 1 second. I have to be doing something wrong. What am I doing wrong here? What should I be doing instead? I'm fairly new to web development, so I'm a little bit in the dark. I am aware that base64 does incur something like a 1.3x size increase, but obviously the upload time here is not scaling with 1.3x. I have done a little bit of console.logging, and
var base64 = reader.result;
takes about a second. So I do not think that the bottleneck is there. The bottleneck has to be in the uploading. But why? Why is a form file input so much faster than a form hidden input with base64?
I apologize for my long winded post, but again, I am new to web development, and don't really understand my problem, so it's hard to be concise while getting all the information across.
Thanks
I am working on a website that allows users to edit photos (in-browser) and then upload them. To edit the images in-browser, I use some JavaScript libraries that work with images in base64. As a result, to POST the image to my server, a simple form with a file input cannot be used. The value of a hidden input is set to a base64 string of the edited image, and that is POSTed. Please see the following, short example.
http://pastebin./PrfWaS3D
Obviously, this is very much stripped down, but it does contain the problem I'm running into. In POSTing a 3MB animated GIF, it took 6.5 minutes. During which, my puter was almost pletely frozen/unresponsive. (Note: This works perfectly for small images, though)
It might be an OS/browser issue, (latest Google Chrome on Ubuntu) but I doubt it. If I put that file input inside the form, and remove base64-ing of data, (i.e. - a standard POSTing of a file) it goes in about one second.
Compare 6.5 minutes to 1 second. I have to be doing something wrong. What am I doing wrong here? What should I be doing instead? I'm fairly new to web development, so I'm a little bit in the dark. I am aware that base64 does incur something like a 1.3x size increase, but obviously the upload time here is not scaling with 1.3x. I have done a little bit of console.logging, and
var base64 = reader.result;
takes about a second. So I do not think that the bottleneck is there. The bottleneck has to be in the uploading. But why? Why is a form file input so much faster than a form hidden input with base64?
I apologize for my long winded post, but again, I am new to web development, and don't really understand my problem, so it's hard to be concise while getting all the information across.
Thanks
Share Improve this question asked Aug 31, 2013 at 16:16 JohnJohn 7462 gold badges11 silver badges16 bronze badges 5- What is your backend server? – arb Commented Aug 31, 2013 at 16:24
-
-A data url is not the same as base64... These days data URLs are mostly UUIDs, not the full base64 body + meta data. Uploading that UUID is useless.- If you really mean to base64 in JS, use
btoa()
. – Rudie Commented Aug 31, 2013 at 16:28 - My backend server? It's PHP. (Is that what you're asking?) – John Commented Aug 31, 2013 at 16:29
- I was wrong. I was talking about Object URLs. My bad. Yours are in fact base64 + meta data. Seems fast enough though: jsfiddle/rudiedirkx/4pLAv (Chrome tells you upload progress. 4M takes about 15 sec for me there. You?) – Rudie Commented Aug 31, 2013 at 16:32
- And after typing that, my puter froze and the tab crashed =) – Rudie Commented Aug 31, 2013 at 16:36
2 Answers
Reset to default 6Since you're using somewhat modern JS API anyway, it might be better to use:
URL.createObjectURL()
to create a URL from a Blob (much faster and inspectable than Data URLs)btoa()
to base64 encode a string (not necessary anymore)FormData
to create a POST request- XHR2 to send it to the server (includes progress even!)
So something like this:
- Get file:
file = input.files[0]
- Convert to typed array, do magic, convert back to Blob:
blob = <magic here>
- Create POST:
fd = new FormData; fd.append('file', blob, 'image.png');
- Upload:
xhr = new XMLHttpRequest; ... xhr.send(fd);
<form action="1.php" method="post">
<input type="text" id="txt" name="txt">
<input type="submit" value="submit" >
</form>
function convertToDataURLviaCanvas(url, callback, outputFormat){
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(outputFormat);
callback(dataURL);
canvas = null;
};
img.src = url;
}
convertToDataURLviaCanvas('1.jpg', function(base64Img){
console.log(base64Img);
document.getElementById('txt').value= base64Img;
});
1.php
echo '<img src="'.$_POST['txt'].'" />';