I find that there's simpler solution compared to the accepted answer.
Read the files using the HTML5 FileReader API with.readAsArrayBuffer
- Create a Blob with the file data and get its url with
window.URL.createObjectURL(blob)
- Create new Image element and set it's src to the file blob url
- Send the image to the canvas. The canvas size is set to desired output size
- Get the scaled-down data back from canvas
viacanvas.toDataURL("image/jpeg",0.7)
(set your own output format and quality)- Attach new hidden inputs to the original form
and transfer the dataURI images basically as normal textOn backend, read the dataURI, decode from Base64, andsave it
As per your question:
Is there a way to compress an image (mostly jpeg, png and gif) directly browser-side, before uploading it
My solution:
Create a blob with the file directly with URL.createObjectURL(inputFileElement.files[0])
.
Same as accepted answer.
Same as accepted answer. Worth mentioning that, canvas size is necessary and use img.width
and img.height
to set canvas.width
and canvas.height
. Not img.clientWidth
.
Get the scale-down image by canvas.toBlob(callbackfunction(blob){}, 'image/jpeg', 0.5)
. Setting 'image/jpg'
has no effect. image/png
is also supported. Make a new File
object inside the callbackfunction
body with let compressedImageBlob = new File([blob])
.
Add new hidden inputs or send via javascript . Server doesn't have to decode anything.
Check https://javascript.info/binary for all information. I came up the solution after reading this chapter.
Code:
<!DOCTYPE html>
<html>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="fileToUpload" id="fileToUpload" multiple>
<input type="submit" value="Upload Image" name="submit">
</form>
</body>
</html>
This code looks far less scary than the other answers..
One has to put everything inside img.onload
. Otherwise canvas
will not be able to get the image's width and height correctly as the time canvas
is assigned.
function upload(){
var f = fileToUpload.files[0];
var fileName = f.name.split('.')[0];
var img = new Image();
img.src = URL.createObjectURL(f);
img.onload = function(){
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
canvas.toBlob(function(blob){
console.info(blob.size);
var f2 = new File([blob], fileName + ".jpeg");
var xhr = new XMLHttpRequest();
var form = new FormData();
form.append("fileToUpload", f2);
xhr.open("POST", "upload.php");
xhr.send(form);
}, 'image/jpeg', 0.5);
}
}
3.4MB
.png
file compression test with image/jpeg
argument set.
|0.9| 777KB |
|0.8| 383KB |
|0.7| 301KB |
|0.6| 251KB |
|0.5| 219kB |