Image Resizing Client-Side With JavaScript Before Upload to the Server

Resize image on client side before uploading to the server

No. PHP is a server side language. You cannot resize images on client side with PHP.

Use HTML5 to resize an image before upload

Here is what I ended up doing and it worked great.

First I moved the file input outside of the form so that it is not submitted:

<input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos(\'#{imageUploadUrl}\')" />
<form id="uploadImageForm" enctype="multipart/form-data">
<input id="name" value="#{name}" />
... a few more inputs ...
</form>

Then I changed the uploadPhotos function to handle only the resizing:

window.uploadPhotos = function(url){
// Read in file
var file = event.target.files[0];

// Ensure it's an image
if(file.type.match(/image.*/)) {
console.log('An image has been loaded');

// Load the image
var reader = new FileReader();
reader.onload = function (readerEvent) {
var image = new Image();
image.onload = function (imageEvent) {

// Resize the image
var canvas = document.createElement('canvas'),
max_size = 544,// TODO : pull max size from a site config
width = image.width,
height = image.height;
if (width > height) {
if (width > max_size) {
height *= max_size / width;
width = max_size;
}
} else {
if (height > max_size) {
width *= max_size / height;
height = max_size;
}
}
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
var dataUrl = canvas.toDataURL('image/jpeg');
var resizedImage = dataURLToBlob(dataUrl);
$.event.trigger({
type: "imageResized",
blob: resizedImage,
url: dataUrl
});
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(file);
}
};

As you can see I'm using canvas.toDataURL('image/jpeg'); to change the resized image into a dataUrl adn then I call the function dataURLToBlob(dataUrl); to turn the dataUrl into a blob that I can then append to the form. When the blob is created, I trigger a custom event. Here is the function to create the blob:

/* Utility function to convert a canvas to a BLOB */
var dataURLToBlob = function(dataURL) {
var BASE64_MARKER = ';base64,';
if (dataURL.indexOf(BASE64_MARKER) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = parts[1];

return new Blob([raw], {type: contentType});
}

var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;

var uInt8Array = new Uint8Array(rawLength);

for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}

return new Blob([uInt8Array], {type: contentType});
}
/* End Utility function to convert a canvas to a BLOB */

Finally, here is my event handler that takes the blob from the custom event, appends the form and then submits it.

/* Handle image resized events */
$(document).on("imageResized", function (event) {
var data = new FormData($("form[id*='uploadImageForm']")[0]);
if (event.blob && event.url) {
data.append('image_data', event.blob);

$.ajax({
url: event.url,
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
//handle errors...
}
});
}
});

Pre- resize multiple images before uploading from client side Jquery Laravel

So, I've no help but I managed to solve the issue by using tweeks....
I'm posting them so it can help someone... Thanks

here i am picking the picture and passing it to be resized and pushing them in array:

 $(document).on('change','#selectfile',function(){
file_obj = this.files;
pictures_array(file_obj);
});

here the function for resizing and store it in array, i'm here restricting ajax function from running until the in array count will not equal the length of files with some validation..:

function pictures_array(file_obj){
var image_count = $('.sequence').length-1;
count = file_obj.length;
var new_count = image_count+count;

console.log(image_count,new_count,count);
if(new_count<=15){
$('.ajax-loader').css("visibility", "visible");

pictures = [];


for(i=0; i<file_obj.length; i++) {
var fileType = file_obj[i].type;
var match = ['image/jpeg', 'image/png', 'image/jpg'];
if(!((fileType == match[0]) || (fileType == match[1]) || (fileType == match[2]) || (fileType == match[3]) || (fileType == match[4]) || (fileType == match[5]))){
var status='false';
}
resizeImages(file_obj[i],function(dataUrl){
var data = dataUrl;
pictures.push(data);
if(!--count) {
ajax(pictures);
}

});

}

}else{
$('#max_limit').html(15);
$('#limit').show();
$('html, body').animate({
scrollTop: $(".main-image").offset().top
}, 2000);
$('#selectfile').val('');
$('#selectfile1').val('');
}
}

heres the ajax call:
i am apending the base64 version of pictures using for loop in the file[]:

function ajax(pictures) {
// console.log(pictures);

var image = new FormData();
var pictures = pictures;
for (var i = 0; i < pictures.length; i++) {
image.append('file[]',pictures[i]);
}


$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
// 'Content-Type': 'multipart/form-data',
},
url: "{{ route('images_private.store',$row->id) }}",
type: "POST",
data: image,
cache: false,
processData: false,
contentType: false,
datatype: 'html',
beforeSend: function(){
$('.ajax-loader').css("visibility", "visible");
},
success:function(response) {
$('#selectfile').val('');
$('#selectfile1').val('');
$('#appendhtml').html(response);
// $('#appendhtml').load('#appendhtml');
setTimeout(function() {
toastr.options = {
closeButton: true,
progressBar: true,
showMethod: 'slideDown',
timeOut: 4000
};
toastr.success('Images uploaded successfully');
}, 1300);
$("#other-image-main").sortable({
cursor: 'move',
opacity: 0.6,
update: function() {
sendOrderToServer();
}
});

},
complete: function(){
$('.ajax-loader').css("visibility", "hidden");
$('#valid_image_type').hide();

},
});
}

and then the last step in the controller:
here i am decoding the base64 to jpeg file and storing it into the server:

if(!File::isDirectory($path)){

File::makeDirectory($path, 0777, true, true);

}
if($request->has('file')){
foreach ($request->file as $image){
$position++;
list($type, $image) = explode(';', $image);
list(, $image) = explode(',', $image);

$image = base64_decode($image);

$source_img = imagecreatefromstring($image);
$filename= uniqid() . '.jpg';
$filepath = $path.$filename ;
$imageSave = imagejpeg($source_img, $filepath);

ImagesPrivate::create([
'user_id'=>$id,
'owner_id'=>$auth,
'name'=>$filename,
'position'=>$position,
'position_change'=>$position,
'delete' => 'pending',
]);

}
}

So, in the end 4.8MB picture is now weigh 316KB thats a success,,,

i am posting this because i haven't found anything like that and it took me time to do this,,, may be i haven't researched properly but this is how i manage to upload multiple images pre-resized on client side without any trigger button...
cuts uploading time to 90%...

Hope that helps someone Thanks
Regards

Javascript resize image to reduce its size before uploading to the server?

According to this link you can use the native JavaScript and HTML5 Canvas features to resize an image on the client-side. I have not tried the instructions in this tutorial but I have used HTML5 Canvas in the past to make a 2D RPG engine that resized images. This tutorial, however, goes further and explains how to create an image for the purposes that you are asking for. Looking over this tutorial, it also provides alternatives if your native browser doesn't support certain features, like "toBlob".

Possible to resize an image (client side) on an html form before upload?

You can use the new FileReader to let the user select an image from their local file system.

Then you can use canvas to resize the image as needed.

enter image description here

This code lets the user select a local image file.

The image will be scaled to half size on the client side.

<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>Image preview example</title>
<script type="text/javascript">
oFReader = new FileReader(), rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;

oFReader.onload = function (oFREvent) {

var img=new Image();
img.onload=function(){
document.getElementById("originalImg").src=img.src;
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width=img.width/2;
canvas.height=img.height/2;
ctx.drawImage(img,0,0,img.width,img.height,0,0,canvas.width,canvas.height);
document.getElementById("uploadPreview").src = canvas.toDataURL();
}
img.src=oFREvent.target.result;
};

function loadImageFile() {
if (document.getElementById("uploadImage").files.length === 0) { return; }
var oFile = document.getElementById("uploadImage").files[0];
if (!rFilter.test(oFile.type)) { alert("You must select a valid image file!"); return; }
oFReader.readAsDataURL(oFile);
}
</script>
</head>

<body onload="loadImageFile();">
<form name="uploadForm">
<table>
<tbody>
<tr>
<td><img id="originalImg"/></td>
<td><img id="uploadPreview"/></td>
<td><input id="uploadImage" type="file" name="myPhoto" onchange="loadImageFile();" /></td>
</tr>
</tbody>
</table>
</form>
</body>
</html>

Modern browsers support the FileReader (but for IE you need 10+).



Related Topics



Leave a reply



Submit