Upload an image using PHP and Javascript


#1

So, after a long time telling myself ‘you should write a tutorial’ I had a bit of time on my hands this morning
and viola! Here it is… :slight_smile:

This tutorial will demonstrate one way of uploading images to your website.
It also allows for the image to be cropped before uploading.
Before we begin I should point out that for the sake of clarity I have not
done everything we should when uploading files - for example storing them
outside the public dir, checking for malicious code etc.
I’ll leave that to you as a further excercise. :wink:

So, let’s begin…

First i am working out of a folder called ‘image_upload’.
Inside this directory I have another folder called ‘imgs’ - this is where we will store the uploaded files.
Next I am using jquery & jcrop, go grab a copy of each and place them in the ‘image_upload’ directory.

Then, create four more blank files in the same directory, three php and one js file named
uploadform.php
image_manipulation.php
success.php
functions.js

All set? Great, let’s rock n roll!



Step One: (the javascript stuff)
Open the function.js file in your favourite editor and paste the following code:

//Submit the form and upload the users image in the background.
function submitimage() {
	$("#image_form").submit(); // auto submit form to upload image
	alert("Uploading image...\n\nIf nothing happens within 3 seconds, click ok!");
}
function updateCoords(c) {
	$('#x').val(c.x);
	$('#y').val(c.y);
	$('#w').val(c.w);
	$('#h').val(c.h);
}
function checkCoords() {
	if(parseInt($('#w').val())) {
		return true;
	}
	alert('Please select a crop region then press submit.');
	return false;
}

//Jquery 
$(document).ready(function() {
	var jcrop_api, boundx, boundy;
	$('#target').Jcrop({
        onSelect:    updateCoords,
        bgColor:     'black',
        bgOpacity:   .4,
		boxWidth: 400, 
		boxHeight: 400
	},
	function(){
		// Use the API to get the real image size
		var bounds = this.getBounds();
		boundx = bounds[0];
		boundy = bounds[1];
		// Store the API in the jcrop_api variable
		jcrop_api = this;
	});
});

This code is responsible for uploading the image in the background.
The first function submits the form.
The second & third functions take care of the coords when we crop the image.
The last bit of code is jquery and calls the required bits n bobs when they’re needed.

You can now close this file, we won’t be needing it again. :slight_smile:



Step Two (the image manipulation class)
Open image_manipulation.php and paste the following code;
[php]

<?php class image_manipulation { public function __construct() {} /* * This deals with uploading the image behind the scenes. */ public function do_upload() { if(isset($_POST['upload_image']) && !isset($_SESSION['img_attributes'])) { $min_w = (isset($_POST['min_w'])) ? $_POST['min_w'] : NULL; $min_h = (isset($_POST['min_h'])) ? $_POST['min_h'] : NULL; $img_cat = (isset($_POST['pagename'])) ? $_POST['pagename'] : NULL; // $success = $this->image_upload($_FILES['img']['name'], $_FILES['img']["type"], $_FILES['img']["size"], $_FILES['img']["tmp_name"], $_FILES['img']["error"], $min_w, $min_h, $img_cat); if($success != 0) { $errors[] = 'The image failed to upload:' . $success; } else { header("Location: /image_upload/uploadform.php"); exit(); } } # end image upload. } /** * This method is responsible for uploading the image behind the scenes. * Note: this has nothing to do with the crop feature! */ public function image_upload($img, $img_type, $img_size, $img_tmp, $img_error, $min_w, $min_h, $img_dir) { $success = 0; if($img_dir != '') { $destination_path = $img_dir; } else { $destination_path = '/imgs/'; } // Error Checking. if($img_error > 0) { switch($img_error) { case 1: $success = 'The uploaded file exceeds the upload max filesize!'; break; case 2: $success = 'The uploaded file exceeds the MAX FILE SIZE!'; break; case 3: $success = 'The uploaded file was only partially uploaded!'; break; case 4: $success = 'No file was uploaded!'; break; case 6: $success = 'Missing a temporary folder!'; break; case 7: $success = 'Failed to write file to disk!'; break; case 8: $success = 'A PHP extension stopped the file upload!'; break; default: $success = 'Unknown upload error!'; break; } #$success = $img_error; // Error! } else { // This sets the maximum amount of memory. ini_set('memory_limit','160M'); $MAX_SIZE = 10; // define a maxim size for the uploaded images in MB if ((($img_type == "image/gif") || ($img_type == "image/jpeg") || ($img_type == "image/jpg") || ($img_type == "image/pjpeg") || ($img_type == "image/png")) && ($img_size < $MAX_SIZE * (1024*1024))) { // Create unique file name. $extension = strtolower(substr(strrchr($img,'.'),1)); $image_name = 'original_' . time() . '.' . $extension; switch($img_type) { case 'image/jpg' : case 'image/jpeg' : case 'image/pjpeg' : $src_img = imagecreatefromjpeg($img_tmp); imagejpeg($src_img, $destination_path.'/'.$image_name); break; case 'image/gif' : $src_img = imagecreatefromgif($img_tmp); imagegif($src_img, $destination_path.'/'.$image_name); break; case 'image/png' : $src_img = imagecreatefrompng($img_tmp); imagepng($src_img, $destination_path.'/'.$image_name); break; default: $success = 'Unknown image type error!'; break; } } else { $success = 'Image type must be a JPEG, GIF or PNG!'; } } $w = imageSX($src_img); $h = imageSY($src_img); if($w == $min_w && $h == $min_h) { $correct_size = 'Y'; // Image correct size } else { if($w < $min_w || $h < $min_h) { $success = 'Image too small (minimum size: ' . $min_w . ' x ' . $min_h . ' px)'; } $correct_size ='N'; // Image incorrect size } if(!is_file($destination_path.'/'.$image_name)) { $success = 1; // Error! } else { // make image array. $_SESSION['img_attributes'] = array ( "img" => $image_name, "img_extension" => $extension, "correct_size" => $correct_size, "destination_path" => $destination_path, "cropped" => 'N' ); $success = 0; // success } return $success; } // End method. /* * This method will process the submitted image. */ public function create_images($watermark=true) { if(isset($_SESSION['img_attributes'])) { // Set some dimensions for the cropped image. $x = $_POST['x']; $y = $_POST['y']; $w = $_POST['w']; $h = $_POST['h']; // $targ_w = $_POST['min_w']; $targ_h = $_POST['min_h']; $jpeg_quality = 100; // image names. $time = time(); $new_image_name = $time . '.jpg'; if($watermark === true) { // watermark file. $watermark_name = $time . '_watermark.jpg'; $watermark_image = 'image_upload/watermark.png'; $watermark_source = imagecreatefrompng($watermark_image); imagealphablending($watermark_source, true); } // uploaded file. $uploaded_image = $_SESSION['img_attributes']['destination_path'] . '/' . $_SESSION['img_attributes']['img']; list($width, $height) = getimagesize($uploaded_image); # set image switch($_SESSION['img_attributes']['img_extension']) { case 'jpg' : case 'jpeg' : case 'pjpeg' : $source_image = imagecreatefromjpeg($uploaded_image); break; case 'gif' : $source_image = imagecreatefromgif($uploaded_image); break; case 'png' : $source_image = imagecreatefrompng($uploaded_image); break; default: $errors[] = 'Unknown image type error, Please use a jpg|png|gif file!'; break; } imagealphablending($source_image, true); if($watermark === true) { // make the watermarked file. imagecopyresized($source_image, $watermark_source, 0, 0, 0, 0, $width, $height, 1000, 1000); $tempimage = $_SESSION['img_attributes']['destination_path'] . '/' . $watermark_name; imagejpeg($source_image, $tempimage, $jpeg_quality); // use the watermarked file as source when resizing.. $watermarked_image = imagecreatefromjpeg($tempimage); } $watermarked_image = isset($watermarked_image) ? $watermarked_image : $source_image; // create some images.. // regular - this will be used on the browse/view item page. $destination_image = imagecreatetruecolor($targ_w/3, $targ_h/3); imagecopyresampled($destination_image, $watermarked_image, 0, 0, $x, $y, $targ_w/3, $targ_h/3, $w, $h); $image = $_SESSION['img_attributes']['destination_path'] . '/' . $new_image_name; imagejpeg($destination_image, $image, $jpeg_quality); // destroy the images in memory. unlink($uploaded_image); unlink($tempimage); imagedestroy($source_image); imagedestroy($watermark_source); imagedestroy($watermarked_image); imagedestroy($destination_image); } return isset($new_image_name) ? $new_image_name : false; } /**/ } ?>

[/php]

WOWSERS - that’s a lot of code!!
Ok, let’s go through it a bit at a time…

Method One: (do_upload)
This checks if $_POST[‘upload_image’] has been submitted and there is no session with an image.
the next three lines create some variables.
$success submits the uploaded image to another method called image_upload. We expect to receive a value of 0 upon success.
anything other is an error. For example, 1 = couldn’t find the file.
If successful, it returns you to the same page.

Note: A quick look at the function.js file here we can see an alert box is set to open upon submitting the form.


Method Two: (image_upload)
This creates a copy of the uploaded image.
First, we check if there is a destination path set, if not, we set one. (this is the path to the imgs folder)
Next we check the $img_error variable and if it’s greater than zero we have a problem.
If there is no error we move to the ‘else’ part of the method.
In here I have allowed for bigger uploads of 10mb.
We then check the type of image being uploaded, jpg, png, etc.

The next two lines we create a unique name for the file using the time.
The ‘switch’ code creates the new image in the same format as was uploaded.

Finally, after a few checks, we set the new details in a $_SESSION variable so we can pick it up after the redirect.


Method Three: (create_images)
This creates our new image in the cropped size. It also adds an optional watermark. (more on this later)
Using our newly created copy of the image, we run through a similar process to above so I won’t write it all out again
as I’m sure you’ll be able to follow along.

The difference here is the watermark, I’ll pick this up later as i don’t want to steer away from the subject at hand…

That just about covers the image_manipulation.php file, you can close this for now. :slight_smile:



Step Three (the upload form.)
Open the uploadform.php file and copy the following code:
[php]

<?php // start a session session_start(); // the height & width of our new image $min_width = 400; $min_height = 250; // the path to the dir for uploaded images. $page_name = 'imgs'; // This deals with uploading the image behind the scenes. include 'image_manipulation.php'; $image = new image_manipulation; $image->do_upload(); # if the form has been submitted, pass it # over to the private _editing_item method. if(isset($_POST['mainform'])) { $errors = array(); // If everything went ok if(empty($errors)) { if(isset($_SESSION['img_attributes'])) { $imgname = image_manipulation::create_images(false); unset($_SESSION['img_attributes']); unset($_POST); } header("Location: /image_upload/success.php?image=$imgname"); exit(); } else { echo '

Please fix the following errors:

'; foreach($errors as $error) { echo "

$error

"; } } } ?>

Upload an image

<?php if(isset($_SESSION['img_attributes']['destination_path'])) { ?> <?php } ?>
Crop Image : Your Image
Click to Confirm :

[/php]

First we start a session and set some values for the width, height and img dir path.
Next we include the image_manipulation.php file, initialise the class and call the
‘do_upload’ method - of course nothing will happen as the $_POST variable is not set.

The ‘if’ clause kicks in when we submit the main form and inside it calls the
create_images method (using an arg of false - this is important, i’ll come back to this later)
This method returns the new image name if successful - use this to enter into a database
or whatever storage method you incorporate, for now though we’re going to tag it onto
the end of a url then redirect us there.
Leaving PHP, we now create the HTML form, well two actually!

Form 1;
This form allows us to select and upload an image and is submitted using javascript
as soon as a file is selected. (onchange())

Form 2;
This allows us to capture other data like name, comments etc. and do whatever we wish
like store in a database/textfile etc.

The last three lines call jquery, jcrop and function.js.



Step Four: (success.php)
This file is only here to display the final image to you, in the real world you would
process the data and do something else…

Open success.php and copy the following line of code:

<img src="imgs/<?php echo $_GET['image']; ?>" alt="New Image">


Now, remember i kept mentioning watermark and i’d come back to it, well here it is…
Firstly you are going to need an image of decent size - say 1000 x 1000 that is
transparent and includes your watermark text.
Place this image in the same directory as the other files.
Open the uploadform.php file and look for image_manipulation->create_images(false);
and change the false to true. This activate the watermark part of the script.
You can see a watermarked example here;

And that my friends concludes this tutorial.
Happy coding!

Red :wink:


#2

Nice tutorial!


#3

Thanks TC :wink: