If you create a CMS (Content Management System) the likelihood is that you'll what users to be able to upload images.  Uploading images is straightforward enough but just needs a little bit of planning.  In this example I am going to check that the image is of an appropriate file type, that it is below a set size and ensure that the file has a unique name.

Create and Configure a Target Folder

The first thing you'll need is a folder on your server for the images. Usually folders on a web server are configured such that visitors via a web browser cannot upload files to them. This makes perfect security sense. In order to be able to write an image we'll need to change the permissions on the folder. On a UNIX server this means setting the directory to 755.

Create the Upload HTML form

From the HTML point of view we need a form. What is different to other forms is the addition of the enctype attribute in the form element. We also need an input and this uses the type file.

<form action="uploader.php" enctype="multipart/form-data" method="post">
<input type="file" name="myFile">
<input type="submit" value="Upload File">
</form>

Check that you want this sort of file

Once you have submitted the form with a file the next thing to do it check you are happy with the size and type of file submitted. You don't want some nasty JS, EXE or PHP on your nice web server. The key to checking out the file is PHP's super global $_FILES. This is an associate array of items that have been uploaded to the server via the HTTP POST method.

Tip: Unsure about super globals - check out $_GET and $_POST in the section on PHP Basics

If you run a print_r() for $_FILES you get the contents of the array, which should look something like this:

print_r($_FILES);
Array ( [myFile] => Array (
  [name] => view1.jpg
  [type] => image/jpeg
  [tmp_name] => /tmp/phpLh4TJG
  [error] => 0
  [size] => 23424 )
)

An error value of 0 means no errors (Tell me more).

Code What that means
0 No Errors - Upload Successful
1 The uploaded file exceeds the upload_max_filesize directive in php.ini
2 The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form
3 The uploaded file was only partially uploaded
4 No file was uploaded
6 Missing a temporary folder
7 Failed to write file to disk. Introduced in PHP 5.1.0.
8 A PHP extension stopped the file upload.

A simple condition and redirect can send the user back and stop any further code executing ie:

$fileError = $_FILES['filmImage']['error'];
if($fileError > 0){
	header("Location:".$returnURL."?err=imgUploadError");
	exit;
}

We can also validate the image size against a maximum file size of our choice:

$maxSize = 100000;
$fileSize = $_FILES['filmImage']['size'];
if($fileSize > $maxSize){
      header("Location:".$returnURL."?err=tooBig");
      exit;
}

Now we do also have a type but as the browser can be tricked as to the type of the file uploaded we'll use a PHP function called exif_imagetype. The PHP docs indicate that this function "reads the first bytes of an image and checks its signature." Perfect for checking for an image. How to do this:

First we'll use $_FILES tmp_name value to get the temporary location of the file. We then create an array of the file types we'll accept. If we check the file to see if its file type is in our array we can then get the true file type of the file and saved that away in a variable:

$fileTempName = $_FILES['filmImage']['tmp_name'];
$trueFileType = exif_imagetype($fileTempName);
$allowedFiles = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
if (in_array($trueFileType, $allowedFiles)) {
    switch($trueFileType){
	case 1 : $fileExt  = ".gif";
	break;
	case 2: $fileExt  = ".jpg";
	break;
	case 3 : $fileExt  = ".png";
	break;
     }
}else{
	header("Location:".$returnURL."?err=WrongFileType");
	exit;
}

Naming the File

We now know the file extension but we need to rename the file. We do this for two reasons - to stop an existing file been overwritten and secondly so that we can give the image a name that suits are naming convention.

In this example I am assuming the uploaded image is part of a form of data been added to my database. I have my database table set up to receive a new record and to add a new auto-incremented primary key. As such I want to use the primary key value of my new record to be used as file name.

$stmt = $mysqli->prepare("INSERT INTO movies(filmName, filmDescription, filmPrice, filmReview) VALUES (?, ?, ?, ?)");
$stmt->bind_param('ssdi', $filmName, $filmDescription, $filmPrice, $filmReview);
$stmt->execute();
$newID = $stmt->insert_id;
$newFileName = $newID . $fileExt;
$stmt->close();

The above adds a new record to my database table called 'movies' and I use the insert_id property to get the primary key value of the new record. This we'll add to the file extension already retrieved to give us a filename something like '32423.jpg'.

Moving the Temporary File

Now we have file name we need to check the location to move it to. This code uses PHP's $_SERVER superglobal to get the current directory. The site is structured with the 'uploadedImages' folder at the same level in the site as the PHP file that is performing the upload.

// Get the path to upload the image to
$myPathInfo = pathinfo($_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF']);
$currentDir = $myPathInfo['dirname'];
$imgDir = $currentDir . '/uploadedImages/';

Tip: Check out this post on Getting Path Information with PHP.

The last step is to move the temporary file to the 'uploadedImages' folder. For this I'll use the PHP method move_uploaded_file().

$newImgLocation = $imgDir . $newFileName;
if(move_uploaded_file($fileTempName, $newImgLocation)){
	header("Location:".$returnURL);
}else{
	header("Location:".$returnURL."?err=UploadProb");
}

Here is the Finished Example

Tip: I use some simple error handling via the URL but other options are available - you could for example use AJAX or store errors in a session.

The Form

<form action="uploader.php" enctype="multipart/form-data" method="post">
  <p class="indent">
    <label for="filmName">Film Name:</label>
    <input type="text" name="filmName" id="filmName" value="">
  </p>
  <p class="indent">
  <label for="filmCert">Certificate:</label>
  <select name="filmCert">
		<?php
			while ($rowCerts = $resultFilmCerts->fetch_assoc()) {
				echo "<option value=\"{$rowCerts['filmCertificate']}\">";
				echo $rowCerts['filmCertificate'];
				echo "</option>";
			}
		?>
        </select>
  </p>
  <p class="indent">
    <label for="filmImage">Film Image</label>
    <input type="file" name="filmImage" required>
  </p>
  <p class="indent">
    <label for="filmDescription">Film Description</label>
    <textarea name="filmDescription" id="filmDescription" cols="45" rows="5"></textarea>
  </p>
 <p class="indent">
    <label for="filmPrice">Film Price</label>
    <input type="text" name="filmPrice" id="filmPrice" value="">
  </p>
  <p>
  <span class="indent">Star Rating:</span>
    <label for="filmReview_1">1</label>
      <input type="radio" name="filmReview" value="1" id="filmReview_1">

    <label for="filmReview_2">2</label>
      <input type="radio" name="filmReview" value="2" id="filmReview_2">

    <label for="filmReview_3">3</label>
      <input type="radio" name="filmReview" value="3" id="filmReview_3">

    <label for="filmReview_4">4</label>
      <input type="radio" name="filmReview" value="4" id="filmReview_4">

    <label for="filmReview_5">5</label>
      <input type="radio" name="filmReview" value="5" id="filmReview_5" checked>
    </p>
  <p>
    <input type="submit" name="button" id="button" value="Insert">
  </p>
</form>

The Processing File

<?php
// Build a queryString free URL return address
if(strpos($_SERVER['HTTP_REFERER'], "?") > 0){
	$returnURL = substr($_SERVER['HTTP_REFERER'], 0, strpos($_SERVER['HTTP_REFERER'], "?"));
}else{
	$returnURL = $_SERVER['HTTP_REFERER'];
}
include_once('includes/conn.inc.php');

// Filter uploads
$filmName = filter_var($_POST['filmName'], FILTER_SANITIZE_STRING);
$filmDescription = filter_var($_POST['filmDescription'], FILTER_SANITIZE_STRING);
$filmCert = filter_var($_POST['filmCert'], FILTER_SANITIZE_STRING);
$filmPrice = filter_var($_POST['filmPrice'], FILTER_VALIDATE_FLOAT);
$filmReview =  filter_var($_POST['filmReview'], FILTER_VALIDATE_INT);

// Check image
$fileError = $_FILES['filmImage']['error'];
// http://php.net/manual/en/features.file-upload.errors.php
if($fileError > 0){
	header("Location:".$returnURL."?err=imgUploadError");
	exit;
}
$maxSize = 100000;
$fileType = $_FILES['filmImage']['type'];
$fileSize = $_FILES['filmImage']['size'];
$fileTempName = $_FILES['filmImage']['tmp_name'];
// 0 not error
//$fileError = $_FILES['filmImage']['error'];
$trueFileType = exif_imagetype($fileTempName);
$allowedFiles = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
if (in_array($trueFileType, $allowedFiles)) {
    if($fileSize > $maxSize){
		header("Location:".$returnURL."?err=tooBig");
		exit;
	}else{
		switch($trueFileType){
			case 1 : $fileExt  = ".gif";
			break;
			case 2: $fileExt  = ".jpg";
			break;
			case 3 : $fileExt  = ".png";
			break;
		}
	}
}else{
	header("Location:".$returnURL."?err=WrongFileType");
	exit;
}
// Get the path to upload the image to
$myPathInfo = pathinfo($_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF']);
$currentDir = $myPathInfo['dirname'];
$imgDir = $currentDir . '/uploadedImages/';
// Insert the other data into the database, get the new ID and create the new filename
$stmt = $mysqli->prepare("INSERT INTO movies(filmName, filmDescription, filmPrice, filmReview) VALUES (?, ?, ?, ?)");
$stmt->bind_param('ssdi', $filmName, $filmDescription, $filmPrice, $filmReview);
$stmt->execute();
$newID = $stmt->insert_id;
$newFileName = $newID . $fileExt;
$stmt->close();
// Update the database with the new image filename
$stmt = $mysqli->prepare("UPDATE movies SET filmImage = ? WHERE filmID = ?");
$stmt->bind_param('si', $newFileName, $newID);
$stmt->execute();
$stmt->close();
// Move the file and redirect
$newImgLocation = $imgDir . $newFileName;
if(move_uploaded_file($fileTempName, $newImgLocation)){
	header("Location:".$returnURL);
}else{
	header("Location:".$returnURL."?err=UploadProb");
}
?>

4 Thoughts to “Uploading Images via PHP”

  1. Hello, the code works fine except for the move file section.. My upload folder is not at the same place than the processing file. I changed your code to this :

    $myPathInfo = pathinfo($_SERVER['DOCUMENT_ROOT']);
    $currentDir = $myPathInfo['dirname'];
    $imgDir = $currentDir . '/html/nicolasdecrem/pics/tracks/';

    But it does not works...

    A little help ?

    Jeff

    1. admin

      Hi Jeff

      As you have hard coded in the path to your upload directory you don't need the $currentDir variable. So therefore you just need:

      $imgDir = '/html/nicolasdecrem/pics/tracks/';

      ... and don't need the $currentDir at all.

      Hope that helps.

  2. Germano

    Hi, i was looking for image upload script with post-get-redirect method and i found this one useful, please can you provide a php database connection file? I will also like to see how you created a database structure for this script.

    Also i found that this code here:

    Certificate:

    fetch_assoc()) {
    echo "";
    echo $rowCerts['filmCertificate'];
    echo "";
    }
    ?>

    need a database connection to work. Could you also provide a full script for multiple image upload?

    Help Please
    Germa

    1. admin

      There is an image uploader tutorial here

Leave a Comment