Handling File & Image Uploads

4.30 (70)

Advanced Error Checking

When a user uploads a file, there is a possibility they upload a file that you do not want, or a file that is too big or meets other criteria. Luckily, the $_FILES superglobal accommodates for this and provides error codes to tell us what has happened.

Before that though, there is another form field that we can use to help us with file uploads. It is a hidden form field called MAX_FILE_SIZE and contains the value in bytes of the maximum file size allowed to be uploaded. This value is for the browser to prevent the users for uploading to big of file, however, it can be easily circumvented. Although PHP will display a specific error code if the file does go over this maximum size.

<input name="MAX_FILE_SIZE" type="hidden" value="100000">


This would aim to prevent the user from uploading a file greater than 100kB in size. PHP itself has its own limit specified in the php.ini, default of 2MB and can be changed to any size. Many hosts will set this up to around 8MB. If a file is greater than this limit then it definitely won't be uploaded.

Checking the error codes


As we found, the $_FILES superglobal contains an error code explaining what has happened during the file upload. The error codes are represented by integer constants (PHP 4.3.0 and higher), so we will use the constant name to describe the error code. They are:

UPLOAD_ERR_OK : Value 0 : File uploaded successfully
UPLOAD_ERR_INI_SIZE : Value 1 : File size exceeded php.ini value
UPLOAD_ERR_FORM_SIZE : Value 2 : File size exceeded MAX_FILE_SIZE form value
UPLOAD_ERR_PARTIAL : Value 3 : File was only partially uploaded
UPLOAD_ERR_NO_FILE : Value 4 : No file was uploaded


Now that we have those codes, we can perform some more advanced error checking:

Error Handling
<html>
<head>
<title>File Uploader</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<?php 
if (isset($_FILES['ourFile'])) {
    if (
$_FILES['ourFile']['error'] == UPLOAD_ERR_OK) {
        
$tempName $_FILES['ourFile']['tmp_name'];
        
$fileName $_FILES['ourFile']['name'];

        
$saveDirectory 'uploads/';
        if (@
move_uploaded_file($tempName$saveDirectory $fileName)) {
            echo 
'File Successfully Uploaded!';
        } else {
            echo 
'There was an error whilst uploading the file.';
        }
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_INI_SIZE) {
        echo 
'File size exceeded maximum PHP upload file size.';
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_FORM_SIZE) {
        echo 
'File size exceeded maximum allowed upload file size.';
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_PARTIAL) {
        echo 
'The file was only partially uploaded.';
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_NO_FILE) {
        echo 
'No File was selected to be uploaded.';
    } elseif (
$_FILES['ourFile']['size'] > 100000) {
        echo 
'Don\'t mess with the form. File not uploaded.';
    }
} else {
    
?>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data" name="upload">
      Please enter a file to upload:<br> 
      <input name="MAX_FILE_SIZE" type="hidden" value="100000">
      <input name="ourFile" type="file"><br> 
      <input name="submit" type="submit" value="Submit"> 
    </form>
    <?php
    
}
?> 
</body>
</html>


This code will go through the error code and check what it equals and then print out the correct error message. Unfortunately, it will also display a PHP error warning, which can only be removed by setting error_reporting(E_ALL ^ E_WARNING) at the top of the script. As the MAX_FILE_SIZE field can be easily fooled by someone who knows what he is doing, then it is advisable to add a check to check the size of the file that has been uploaded, and check if it is greater than the size we put in MAX_FILE_SIZE. If the file is greater than this size, either the browser doesn't support the field, or someone was messing with your form trying to upload files that were above your set limit.


Checking File Type


Occasionally, you may only want the user to be able to upload files of a certain type. We can restrict what the user uploads by checking the extension of the file they uploaded. Unfortunately there is no way to definitely check if the file is of the correct type always as the user could change the extension, however, we can try.

We are going to use the example of uploading images as this file type can always be checked fully. We are going to do two things; firstly, check that the extension matches an image extension, and secondly we are going to attempt to check the image size. If we can't check the image size, then it isn't an image.

Type Validation
<html>
<head>
<title>File Uploader</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<?php 

if (isset($_FILES['ourFile'])) {
    if (
$_FILES['ourFile']['error'] == UPLOAD_ERR_OK) {
        
$tempName $_FILES['ourFile']['tmp_name'];
        
$fileName $_FILES['ourFile']['name'];
        
/* Check if it is really an image */
        
$imageTypes = array ('jpeg''jpg''gif''png');
        
$position strlen($fileName) - (strpos($fileName'.'));
        
$extension substr($fileName, -$position+1$position);
    
        if ((
in_array(strtolower($extension), $imageTypes)) && getimagesize($tempName)) {
    
            
$saveDirectory 'uploads/';
            if (@
move_uploaded_file($tempName$saveDirectory $fileName)) {
                echo 
'File Successfully Uploaded!';
            } else {
                echo 
'There was an error whilst uploading the file.';
            }
        } else {
            echo 
'Not a valid image format. Only jpeg, jpg, gif and png please.';
        }
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_INI_SIZE) {
        echo 
'File size exceeded maximum PHP upload file size.';
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_PARTIAL) {
        echo 
'The file was only partially uploaded.';
    } elseif (
$_FILES['ourFile']['error'] == UPLOAD_ERR_NO_FILE) {
        echo 
'No File was selected to be uploaded.';
    } elseif (
$_FILES['ourFile']['size'] > 100000) {
        echo 
'File exceeds maximum file size. File not uploaded.';
    }
} else {
    
?>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data" name="upload">
      Please enter an image to upload:<br> 
      <input name="ourFile" type="file"><br> 
      <input name="submit" type="submit" value="Submit"> 
    </form>
    <?php 
    
}
?>
</body>
</html>


Above we essentially have the same script as before, with our type checking added. We have declared an array called $imageTypes which contains the types of images that we are permitting. We then get the extension of the file that was uploaded, by using a combination of the substr and strpos functions. The substr function gets a part of a string from position a for a certain length. Alternatively, strpos() returns the position of a certain character in a string.

We then use in_array() to check if our found extension is in our array of valid image types and if not display an error. At the same time, we do our image check using getimagesize(). It will return an array (true) on success or false on failure (and an E_WARNING error).

We could change this script to only accept txt, doc and html files, however we would have to remove our getimagesize() function otherwise it would return false. Hence, it wouldn't be as certain that the correct file was uploaded. Finally, onto multiple file uploads.
Rate this article: BAD 1 2 3 4 5   GOOD
<<     Page 2 of 3    >>

Build Your Own Database Driven Website Using PHP & MySQL

  • Installation instructions for Windows, Linux and Mac OS X
  • Instantly apply working code examples from the book to your Website
  • Build a working Content Management System from scratch
  • Master MySQL database administration
  • Fully updated for PHP 5

       Download FREESample Chapters Now!

Ads

PHPNerds Newsletter