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

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>
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.
Why not simply
img.src = window.URL.createObjectURL(file)
?– bigless
Jun 30 at 23:01