Fix: PHP upload form not working.

This troubleshooting guide should help you figure out why your PHP upload form isn’t working. In some cases, you may find that the $_FILES array is completely empty, despite the fact that a file has been selected and uploaded.

Upload debug script.

If you are looking for a quick and easy answer, try placing the following code at the top of your upload script:

/**
 * Check to see if POST was used and that its content length is less than the value in post_max_size
 */
$requestType = $_SERVER['REQUEST_METHOD'];
if($requestType != 'POST'){
    echo 'Request type was ' . $requestType . ' - File uploads will only work with POST. Are you using method="post" in your form element?<br>';
    exit;
} else{
    
    if(isset($_SERVER['CONTENT_TYPE'])){
        $contentType = strtolower($_SERVER['CONTENT_TYPE']);
        if(!stristr($contentType, 'multipart/form-data')){
            echo 'Could not find multipart/form-data in Content-Type. Did you use enctype="multipart/form-data" in your form element?<br>';
        }
    }
    
    if(isset($_SERVER['CONTENT_LENGTH'])){
        $postSize = $_SERVER['CONTENT_LENGTH'];
        $maxPostSize = ini_get('post_max_size');
        if($maxPostSize == 0){
            echo 'post_max_size is set to 0 - unlimited.<br>';
        } else{
            if(strlen($maxPostSize) > 1){
                $lastChar = substr($maxPostSize, -1);
                $maxPostSize = substr($maxPostSize, 0, -1);
                if($lastChar == 'G'){
                    $maxPostSize = $maxPostSize * 1024 * 1024 * 1024;
                }
                if($lastChar == 'M'){
                    $maxPostSize = $maxPostSize * 1024 * 1024;
                }
                if($lastChar == 'K'){
                    $maxPostSize = $maxPostSize * 1024;
                }
                if($postSize > $maxPostSize){
                    echo 'The size of the POST request (' . $postSize . ' bytes) exceeded the limit of post_max_size (' . $maxPostSize . ' bytes) in your php.ini file<br>';
                    exit;
                }
            } else{
                if($postSize > $maxPostSize){
                    echo 'The size of the POST request (' . $postSize . ' bytes) exceeded the limit of post_max_size (' . $maxPostSize . ' bytes) in your php.ini file<br>';
                    exit;
                }
            }
            
        }
    } else{
        echo 'CONTENT_LENGTH not found. Make sure that your POST request is smaller than the ' . ini_get('post_max_size') . ' post_max_size in php.ini<br>';
    }
}


$tempFolder = ini_get('upload_tmp_dir');
if(strlen(trim($tempFolder)) == 0){
    echo 'upload_tmp_dir was blank. No temporary upload directory has been set in php.ini<br>';
    exit;
} else{
    echo 'upload_tmp_dir is set to: ' . $tempFolder . '<br>';
}

if(!is_dir($tempFolder)){
    echo 'The temp upload directory specified in upload_tmp_dir does not exist: ' . $tempFolder . '<br>';
    exit;
} else{
    echo $tempFolder . ' is a valid directory<br>';
}

if(!is_writable($tempFolder)){
    echo 'The temp upload directory specified in upload_tmp_dir is not writeable: ' . $tempFolder . '<br>';
    echo 'Does PHP have permission to write to this directory?<br>';
    exit;
} else{
    echo $tempFolder . ' is writeable<br>';
}

$write = file_put_contents($tempFolder . '/' . uniqid(). '.tmp', 'test');
if($write === false){
    echo 'PHP could not create a file in ' . $tempFolder . '<br>';
    exit;
} else{
    echo 'PHP successfully created a test file in: ' . $tempFolder . '<br>';
}

if(ini_get('file_uploads') == 1){
    echo 'The file_uploads directive in php.ini is set to 1, which means that your PHP configuration allows file uploads<br>';
} else{
    echo 'The file_uploads directive in php.ini has been set to 0 - Uploads are disabled on this PHP configuration.<br>';
    exit;
}

if(empty($_FILES)){
    echo 'The $_FILES array is empty. Is your form using method="post" and enctype="multipart/form-data"? Did the size of the file exceed the post_max_size in PHP.ini?';
    exit;
} else{
    foreach($_FILES as $file){
        if($file['error'] !== 0){
            echo 'There was an error uploading ' . $file['name'] . '<br>';
            switch($file['error']){
                case 1:
                    echo 'Size exceeds the upload_max_filesize directive in php.ini<br>';
                    break;
                case 2:
                    echo 'Size exceeds the MAX_FILE_SIZE field in your HTML form<br>';
                    break;
                case 3:
                    echo 'File was only partially uploaded<br>';
                    break;
                case 4:
                    echo 'No file was selected by the user<br>';
                    break;
                case 6:
                    echo 'PHP could not find the temporary upload folder<br>';
                    break;
                case 7:
                    echo 'PHP failed to write to disk. Possible permissions issue?<br>';
                    break;
                case 8:
                    echo 'A PHP extension prevented the file from being uploaded.<br>';
                    break;
                default:
                    echo 'An unknown error occured: ' . $file['error'] . '<br>';
                    break;
            }
        } else{
            echo $file['name'] . ' was successfully uploaded to ' . $file['tmp_name'] . '<br>';
        }
    }
}

The PHP above will attempt to detect some of the most common issues that people have with upload forms. Hopefully, it will point you in the right direction!

enctype

The first thing you should do is make sure that you’ve set the correct enctype attribute on your form element. This attribute basically tells the server how the incoming form data should be encoded. If you forgot to add enctype to your form, no file will be uploaded and the $_FILES array will remain empty:

<form enctype="multipart/form-data" action="upload.php" method="POST">
    Select File: <input name="user_file" type="file" /><br />
    <input type="submit" name="upload" value="Upload File" />
</form>

In this particular case, we’ve set enctype to “multipart/form-data” instead of the default “application/x-www-form-urlencoded”. Setting enctype to “multipart/form-data” prevents data from being encoded.

Use POST, as GET doesn’t support uploads.

You will need to make sure that your HTML form has set the method attribute to “POST”, as file uploads are supported in GET requests (see the above code for an example of “POST” being set as the form method). If the method attribute in your form is not set, then the form will send a GET request by default.

Check your PHP’s file_uploads configuration.

In your php.ini configuration file, you will find a directive called file_uploads. This directive specifies whether PHP should allow HTTP uploads or not. In default PHP installations, this is given the value “1”, which is BOOLEAN for TRUE – meaning file uploads are allowed by default. However, if your web host has disabled file uploads, then you may find that this directive has been set to “0”. To check the value of this directive, you can simply check your PHP.ini file. If you do not have access to the PHP.ini file, then you can use the following code:

<?php

//Use ini_get to get the value of 
//the file_uploads directive
if(ini_get('file_uploads')){
    echo 'file_uploads is set to "1". File uploads are allowed.';
} else{
    echo 'Warning! file_uploads is set to "0". File uploads are NOT allowed.';
}

Check your post_max_size and upload_max_filesize settings.

These are two PHP.ini directives that could potentially stop your upload form from working.

  • upload_max_filesize: The upload_max_filesize directive specifies the maximum size of a file that can be uploaded to the server. By default, this is set to “2M” – meaning 2MB. If a file is larger than the value of this directive, it will not be uploaded. In the past, I have seen this causing 500 Internal Server Errors!
  • post_max_size: This directive sets the maximum size of post data that can be submitted to the server. By default, it is set to “8M”. This means that all POST data must be 8MB in size or less. If the file that you are uploading is 9MB in size, then it will be discarded by the server.

Note that the post_max_size directive should always be larger than upload_max_filesize, as it specifies the max size of both regular form POST data AND the uploaded file data.

When you are setting the values for these directives, make sure that you use a single “M” – not “MB”. i.e. If you want your upload_max_filesize to be 80MB, then you will need to use “80M”, not “80MB”. If you omit the “M” character and use an integer, then PHP will interpret the value as bytes.

Temporary directory not writable?

If you’ve reached this part of the troubleshooting guide, then it is fair to say that something funny is going on. The next port of call is to check if your server’s temporary folder is writable (i.e. it exists and that web server has permission to save files to it). When a file is uploaded to the server, it is automatically saved to the temporary folder until you choose to move it. This folder is set in the PHP.ini file under the directive upload_tmp_dir.

Have a look at the following piece of PHP code, which attempts to check if the upload_tmp_dir directory is available:

//Check to see if the temporary folder
//is writable.

$tempFolder = ini_get('upload_tmp_dir');

echo 'Your upload_tmp_dir directive has been set to: "' . $tempFolder . '"<br>';

//Firstly, lets make sure that the upload_tmp_dir
//actually exists.
if(!is_dir($tempFolder)){
    throw new Exception($tempFolder . ' does not exist!');
} else{
    echo 'The directory "' . $tempFolder . '" does exist.<br>';
}

if(!is_writable($tempFolder)){
    throw new Exception($tempFolder . ' is not writable!');
} else{
    echo 'The directory "' . $tempFolder . '" is writable. All is good.<br>';
}

If you run the code above and no exceptions are thrown, then it is fair to say that the issue isn’t with your upload_tmp_dir directory.

Is the $_FILES array empty?

In the script that handles your uploaded files, do a var_dump on the $_FILES array like so:

<?php

var_dump($_FILES);

Is the $_FILES array empty? If it isn’t – then the files are being uploaded to the temporary directory on your server. If the $_FILES array is empty, then you’ve probably messed up on one of the pitfalls that were listed above.

Enable PHP errors.

At this stage, I think it’s a good idea to enable PHP’s error reporting so that we can see what is actually happening. Maybe you’re getting a blank page or maybe the server is responding with an unhelpful 500 Internal Server Error page.

If the files are being uploaded but they are not being moved to the relevant directory, then it is probably because the file path doesn’t exist (typos) or the correct permissions have not been set. To see what’s actually going wrong, try placing the following piece of code at the top of your upload script:

<?php

//Enable error reporting.
error_reporting(E_ALL);
ini_set("display_errors", 1);

Hopefully, this troubleshooting guide helped you to fix your PHP upload form – or at the very least, it pointed you in the right direction.