toDataURL's output is base64, how to reduce the uploading time and bandwidth of a factor 1/3?

Multi tool use
Multi tool use


toDataURL's output is base64, how to reduce the uploading time and bandwidth of a factor 1/3?



The goal of the following code is to compress the input file (2 MB JPG file => 500 KB file) and then upload it to server when submitting the <form>.


<form>



When importing an image from a JPG file into a canvas, and exporting it with toDataURL with:


toDataURL




function doit() {
var file = document.getElementById('file').files[0],
canvas = document.getElementById('canvas'),
hidden = document.getElementById('hidden'),
ctx = canvas.getContext("2d"),
img = document.createElement("img"),
reader = new FileReader();

reader.onload = function(e) {
img.src = e.target.result;
}

img.onload = function () {
ctx.drawImage(img, 0, 0);
hidden.value = canvas.toDataURL("image/jpeg", 0.5);
}
reader.readAsDataURL(file);
}


<input type="file" onchange="doit();" id="file" />

<form action="/upload" method="post">
<input type="hidden" id="hidden" />
<input type="submit" />
</form>

<canvas id="canvas" style="display: none" />



it works, but the output hidden field in the <form> is base64-encoded, i.e. something like:


hidden


<form>


data:image/jpeg;base64,/9j/4AAQSkZJRgAB...



It is well known that base64 uses 1.3333 times the normal size of binary data.



Question: how to avoid to waste 1/3 of data in uploading time (client => server) and bandwidth in this case, i.e. when submitting the <form>?


<form>



Note: I think the problem will be the same if I use AJAX instead of <form> submission, isn't it?


<form>





Why not simply img.src = window.URL.createObjectURL(file)?
– bigless
Jun 30 at 23:01


img.src = window.URL.createObjectURL(file)





@bigless The goal is not really to just load the file in a img, but rather to compress it (2 MB JPG file => 500 KB file, thus the "quality factor", here 0.5, is important) and then upload it to server, either when submitting a <form> or with AJAX
– Basj
Jul 1 at 8:07



img




1 Answer
1




var jsForm = null;

function doit() {
var file = document.getElementById('file').files[0],
canvas = document.getElementById('canvas'),
ctx = canvas.getContext("2d"),
img = document.createElement("img");

img.src = window.URL.createObjectURL(file);

img.onload = function () {
if (!jsForm) {
jsForm = new FormData();
}
ctx.drawImage(img, 0, 0);
canvas.toBlob(function(blob) {
jsForm.set('image', blob, file.name);
}, "image/jpeg", 0.5);
}
}

var form = document.getElementById('form');
form.onsubmit = function(e) {
e.preventDefault();
if (!jsForm) return;
var request = new XMLHttpRequest();
request.open(this.method||'POST', this.action||'/');
request.send(jsForm);
jsForm = null;
}


<form method="POST" action ="/upload" id="form">
<input type="file" onchange="doit();" id="file" />
<button>Submit</button>
</form>
<canvas id="canvas" style="display: none" />





Thank you very much. Instead of request.open and request.send immediately, how would it be possible to add this formdata to an exist <form id="form1"> <input ...> ... </form> which also contains a submit button, thus allowing the user to choose when he wants to post the form?
– Basj
Jul 2 at 13:01


request.open


request.send


<form id="form1"> <input ...> ... </form>


submit





@Basj You cant programatically manipulate with file input which means that you have to use ajax. I updated answer.
– bigless
Jul 2 at 14:15







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

NBx0LTX T6hatWPNcsoh6BLZGSAdL,7OPtxIjkaZ,c32fGnkjAVyCQbH6Yv3x2nXCvgjrwADPIMgHj X 3CFOu54XSB,w 8U0Nb fn ld
Mr16ABSeWKYu,8ml64iNLt7LXa86 tj6

Popular posts from this blog

Boo (programming language)

Rothschild family