Ajax Image Upload and Resize with jQuery and PHP

There are plenty of great image uploader scripts on the net, but you may find them complicated to implement, especially if you are novice one. Those uploader(s) come with additional scripts and files which you may not even need, so sometimes your best bet is to code your own image upload and resize script, which will serve the purpose and keep things simple.
  • 5.2.0+
  • 1.6.1+
Today we are going to create an Ajax based image upload and resize script, which means the image file will be uploaded to server using Ajax request. We will also be using HTML5 File API to check file size and image type before uploading, then with PHP support we will create two images, a resized version and a thumbnail from original image file. The examples you'll find here are pretty easy to understand. Ajax Image Uploader

HTML Image Upload Form

In HTML form, we need one file input field as shown in code below, notice the multiple="multiple" attribute in input field, it let's us select multiple files, you may remove it if you only accept single file.
HTML
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
<div class="form-wrap"> <form action="process.php" method="post" enctype="multipart/form-data" id="upload_form"> <input name="__files[]" type="file" multiple="multiple" /> <input name="__submit__" type="submit" value="Upload"/> </form> <div id="output"><!-- error or success results --></div> </div>

jQuery

Thanks to HTML5 for new File API, we can now do things like checking file size, type etc. But we also want to make sure client browser supports this feature. Most modern browsers comes with File API support, but for old browsers (like IE8), we can display a nice message like so:
JQUERY
  • 1
  • 2
  • 3
  • 4
  • 5
$("#upload_form").on( "submit", function(event) {//on form submit if(!window.File && window.FileReader && window.FileList && window.Blob){ //if browser doesn't supports File API alert("Your browser does not support new File API! Please upgrade."); } })

Checking file size/type with HTML5 File API

Once we know the browser supports File API, we can start taking things further. Before we send our files directly to server, we want to make sure, file size is not too big and it is an image file. We also want to limit number of files user can upload. Here's the example jQuery code :
JQUERY
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
$("#upload_form").on( "submit", function(event) {//on form submit var proceed = true; //set proceed flag if(!window.File && window.FileReader && window.FileList && window.Blob){ //if browser doesn't supports File API alert("Your browser does not support new File API! Please upgrade."); proceed = false; }else{ //Limit Files Selection var total_selected_files = this.elements['__files[]'].files.length; //number of files selected if(total_selected_files > 3){ //limit number of files allowed to 3 alert( "You have selected "+total_selected_files+" file(s), 3 is maximum!"); //notify user proceed = false; } //iterate files in file input field var total_files_size = 0; $(this.elements['__files[]'].files).each(function(i, ifile){ if(ifile.value !== ""){ //continue only if file(s) are selected if(['image/png', 'image/gif', 'image/jpeg', 'image/pjpeg'].indexOf(ifile.type) === -1){ //check unsupported file alert( "<b>"+ ifile.name + "</b> is unsupported file type!"); proceed = false; } total_files_size = total_files_size + ifile.size; //add file size to total size } }); //if total file size is greater than max file size if(total_files_size > 1048576){ alert( "Make sure total file size is less than 1 MB!"); proceed = false; } } })
Now let's put things together, this time we also use jQuery Ajax. As you can see in code below, we check file size, type and limit the selection of multiple files, then if everything looks good, we create FormData object new FormData() which will be sent to server using jQuery Ajax.
JQUERY
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
//configuration var max_file_size = 2048576; //allowed file size. (1 MB = 1048576) var allowed_file_types = ['image/png', 'image/gif', 'image/jpeg', 'image/pjpeg']; //allowed file types var result_output = '#output'; //ID of an element for response output var my_form_id = '#upload_form'; //ID of an element for response output var total_files_allowed = 3; //Number files allowed to upload //on form submit $(my_form_id).on( "submit", function(event) { event.preventDefault(); var proceed = true; //set proceed flag var error = []; //errors var total_files_size = 0; if(!window.File && window.FileReader && window.FileList && window.Blob){ //if browser doesn't supports File API error.push("Your browser does not support new File API! Please upgrade."); //push error text }else{ var total_selected_files = this.elements['__files[]'].files.length; //number of files //limit number of files allowed if(total_selected_files > total_files_allowed){ error.push( "You have selected "+total_selected_files+" file(s), " + total_files_allowed +" is maximum!"); //push error text proceed = false; //set proceed flag to false } //iterate files in file input field $(this.elements['__files[]'].files).each(function(i, ifile){ if(ifile.value !== ""){ //continue only if file(s) are selected if(allowed_file_types.indexOf(ifile.type) === -1){ //check unsupported file error.push( "<b>"+ ifile.name + "</b> is unsupported file type!"); //push error text proceed = false; //set proceed flag to false } total_files_size = total_files_size + ifile.size; //add file size to total size } }); //if total file size is greater than max file size if(total_files_size > max_file_size){ error.push( "You have "+total_selected_files+" file(s) with total size "+total_files_size+", Allowed size is " + max_file_size +", Try smaller file!"); //push error text proceed = false; //set proceed flag to false } var submit_btn = $(this).find("input[type=submit]"); //form submit button //if everything looks good, proceed with jQuery Ajax if(proceed){ submit_btn.val("Please Wait...").prop( "disabled", true); //disable submit button var form_data = new FormData(this); //Creates new FormData object var post_url = $(this).attr("action"); //get action URL of form //jQuery Ajax to Post form data $.ajax({ url : post_url, type: "POST", data : form_data, contentType: false, cache: false, processData:false, mimeType:"multipart/form-data" }).done(function(res){ // $(my_form_id)[0].reset(); //reset form $(result_output).html(res); //output response from server submit_btn.val("Upload").prop( "disabled", false); //enable submit button once ajax is done }); } } $(result_output).html(""); //reset output $(error).each(function(i){ //output any error to output element $(result_output).append('<div class="error">'+error[i]+"</div>"); }); });

Processing Image

The backbone of this uploader is this PHP file, this is where uploaded image files are resized and saved, then outputted back to browser. Below is the working PHP code which can handle multiple image files. You can go through the it and understand how this code really works. But if you still find it bit complicated, don't worry I've converted following code in a separate PHP class in download section, which you can include in your project, play with it or even contribute if you can improve the code.
PHP
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
<?php ############ Configuration ############## $config["image_max_size"] = 500; //Maximum image size (height and width) $config["thumbnail_size"] = 200; //Thumbnails will be cropped to 200x200 pixels $config["thumbnail_prefix"] = "thumb_"; //Normal thumb Prefix $config["destination_folder"] = 'home/Website/ajax-image-upload/uploads/'; //upload directory ends with / (slash) $config["thumbnail_destination_folder"] = 'home/Website/ajax-image-upload/uploads/'; //upload directory ends with / (slash) $config["upload_url"] = "http://website/ajax-image-upload/uploads/"; $config["quality"] = 90; //jpeg quality if(!isset($_SERVER['HTTP_X_REQUESTED_WITH'])) { exit; //try detect AJAX request, simply exist if no Ajax } if(!isset($_FILES['__files']) || !is_uploaded_file($_FILES['__files']['tmp_name'][0])){ die('Image file is Missing!'); } //count total files in array $file_count = count($_FILES["__files"]["name"]); if($file_count > 0){ //there are more than one file? no problem let's handle multiple files for ($x = 0; $x < $file_count; $x++){ //Loop through each uploaded file //if there's file error, display it if ($_FILES["__files"]['error'][$x] > 0) { print get_upload_error($x); exit; } //Get image info from a valid image file $im_info = getimagesize($_FILES["__files"]["tmp_name"][$x]); if($im_info){ $im["image_width"] = $im_info[0]; //image width $im["image_height"] = $im_info[1]; //image height $im["image_type"] = $im_info['mime']; //image type }else{ die("Make sure image <b>".$_FILES["__files"]["name"][$x]."</b> is valid image file!"); } //create image resource using Image type and set the file extension switch($im["image_type"]){ case 'image/png': $img_res = imagecreatefrompng($_FILES["__files"]["tmp_name"][$x]); $file_extension = ".png"; break; case 'image/gif': $img_res = imagecreatefromgif($_FILES["__files"]["tmp_name"][$x]); $file_extension = ".gif"; break; case 'image/jpeg': case 'image/pjpeg': $img_res = imagecreatefromjpeg($_FILES["__files"]["tmp_name"][$x]); $file_extension = ".jpg"; break; default: $img_res = 0; } //set our file variables $unique_id = uniqid(); //unique id for random filename $new_file_name = $unique_id . $file_extension; $destination_file_save = $config["destination_folder"] . $new_file_name; //file path to destination folder $destination_thumbnail_save = $config["thumbnail_destination_folder"] . $config["thumbnail_prefix"]. $new_file_name; //file path to destination thumb folder if($img_res){ ###### resize Image ######## //Construct a proportional size of new image $image_scale = min($config["image_max_size"]/$im["image_width"], $config["image_max_size"]/$im["image_height"]); $new_width = ceil($image_scale * $im["image_width"]); $new_height = ceil($image_scale * $im["image_height"]); //Create a new true color image $canvas = imagecreatetruecolor($new_width, $new_height); $resample = imagecopyresampled($canvas, $img_res, 0, 0, 0, 0, $new_width, $new_height, $im["image_width"], $im["image_height"]); if($resample){ $save_image = save_image_file($im["image_type"], $canvas, $destination_file_save, $config["quality"]); //save image if($save_image){ print '<img src="'.$config["upload_url"] . $new_file_name. '" />'; //output image to browser } } if(is_resource($canvas)){ imagedestroy($canvas); //free any associated memory } ###### Generate Thumbnail ######## //Offsets if( $im["image_width"] > $im["image_height"]){ $y_offset = 0; $x_offset = ($im["image_width"] - $im["image_height"]) / 2; $s_size = $im["image_width"] - ($x_offset * 2); }else{ $x_offset = 0; $y_offset = ($im["image_height"] - $im["image_width"]) / 2; $s_size = $im["image_height"] - ($y_offset * 2); } //Create a new true color image $canvas = imagecreatetruecolor($config["thumbnail_size"], $config["thumbnail_size"]); $resample = imagecopyresampled($canvas, $img_res, 0, 0, $x_offset, $y_offset, $config["thumbnail_size"], $config["thumbnail_size"], $s_size, $s_size); if($resample){ $save_image = save_image_file($im["image_type"], $canvas, $destination_thumbnail_save, $config["quality"] ); if($save_image){ print '<img src="'.$config["upload_url"] . $config["thumbnail_prefix"]. $new_file_name. '" />'; } } if(is_resource($canvas)){ imagedestroy($canvas); //free any associated memory } } } } //funcion to save image file function save_image_file($image_type, $canvas, $destination, $quality){ switch(strtolower($image_type)){ case 'image/png': return imagepng($canvas, $destination); //save png file case 'image/gif': return imagegif($canvas, $destination); //save gif file case 'image/jpeg': case 'image/pjpeg': return imagejpeg($canvas, $destination, $quality); //save jpeg file default: return false; } } function get_upload_error($err_no){ switch($err_no){ case 1 : return 'The uploaded file exceeds the upload_max_filesize directive in php.ini.'; case 2 : return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'; case 3 : return 'The uploaded file was only partially uploaded.'; case 4 : return 'No file was uploaded.'; case 5 : return 'Missing a temporary folder. Introduced in PHP 5.0.3'; case 6 : return 'Failed to write file to disk. Introduced in PHP 5.1.0'; } }
That's all you need to create an Ajax based image upload and resize script. The downloadable file contains sample script. Hope it will help you create interesting upload form for your website.
Next :Add Progressbar to your Upload form.
Ajax Image Upload and Resize with ImageMagick and Ajax File Upload (Progressbar) Good luck!
New question is currently disabled!