Articles in Get and Post Category

PHP File Upload

There are several form fields to get textual inputs from users and file upload fields let the input be files. PHP has a built-in array called $_FILES that gets populated once a file is uploaded.

Let’s take an example and see the behavior of file upload fields. Think following form (file-upload.html) allows the users of your PHP application to submit their username and a profile picture.

<form name="frmFileUpload" method="post" enctype="multipart/form-data" action="file-upload.php">
Username: <input type="text" name="txtUsername" /><br />
Photo: <input type="file" name="filePhoto" /><br />
<input type="submit" name="btnSubmit" value="Submit" />

When you run this file, it would look like below in your web browser (No CSS styles have been applied since this just for illustration).

File Upload Browse Button

Let’s analyze the specific items related to file uploading in this form.

  • First you can see a new attribute called enctype is added to the <form> tag. This attribute specifies how data should be encoded before sending to the web server. Its default value is application/x-www-form-urlencoded which is optional to specify.
  • The <input> tag with the type file is the file upload field and it creates a file browser button in the web browser.
  • The method of the form should be post (You can try get in the examples. You would see that $_FILES array doesn’t get populated).

Now let’s create file-upload.php, simply having var_export() debugging function to examine $_POST and $_FILES array.


echo '<pre>';
echo '</pre>';

echo '<pre>';
echo '</pre>';


Once you submitted the form, provided that you entered Robin to txtUsername and browsed a file called photo.gif for filePhoto, the output of file-upload.php would be like below.

array (
  'txtUsername' => 'Robin',
  'btnSubmit' => 'Submit',

array (
  'filePhoto' =>
  array (
    'name' => 'photo.gif',
    'type' => 'image/gif',
    'tmp_name' => '/tmp/phptXxJdC',
    'error' => 0,
    'size' => 178890,

This implies that an array element called $_FILES['filePhoto'] has been populated for the file you uploaded. It’s again an array that contains details of the uploaded file. If you had more than one file upload fields in your form, for each field a $_FILES array element will be populated.

  • name contains the file name of the uploaded file.
  • type contains the mime type of the uploaded file.
  • tmp_name contains the temporary location of the uploaded file (We need to copy it to a permanent location).
  • error contains the error code. If no errors occurred during the upload, its value will be zero.
  • size contains the file size of uploaded file in bytes.

Now let’s modify file-upload.php to apply some restrictions against the uploaded file and to move it to a permanent location.


$error = '';

if ($_FILES['filePhoto']['error'] > 0) {
    $error = 'Sorry, there was an error in uploading the file';
} elseif ($_FILES['filePhoto']['type'] != 'image/gif') {
    $error = 'Only .gif files are allowed';
} elseif ($_FILES['filePhoto']['size'] >  51200) { // Bigger than 50KB
    $error = 'Files size should be less than 50KB';
} else {

    $sizeInfo = getimagesize($_FILES['filePhoto']['tmp_name']);

    if ($sizeInfo[0] > 100 || $sizeInfo[1] > 125) {
        $error = 'Image dimensions should be within 100*125';
    } else {
        move_uploaded_file($_FILES['filePhoto']['tmp_name'], "photos/".$_POST['txtUsername'].".gif");


if ($error == '') {
    echo 'Your photo was uploaded successfully';
} else {
    echo $error;


The above code will only allow,

  • Images of type GIF.
  • Images less than 50KB.
  • Images less that 100 pixels in width and 125 pixels in height.

getimagesize() is a specific built-in function for images and returns an array containing details of the given image. Its first element contains the width of the image while second element contains the height. It will return false for file types other than images.

move_uploaded_file() first checks whether the given file is a valid file uploaded via post method. If so, it moves the file to the given location. In this case, it assumes that there is a directory called photos (make sure write permissions are set for it) where file-upload.php resides and stores the image according to given username (in this case as Robin.gif).

Mime Types

Mime type of a file implies what kind of content it contains. In above case, it’s image/gif meaning that the file is an image file of GIF type. This information is sent by the web browser to the web server (Since it’s sent by the client and PHP doesn’t verify it, PHP manual instructs not to rely on it).

There is a possibility that different browsers send different mime types for the same file. For an example, if you uploaded a JPG file, Firefox will show its mime type as image/jpeg and IE will show it as image/pjpeg.

Therefore when you want to restrict to a certain file type, try (write a testing upload script) a file of that type in different web browsers that you think your users would use and examine mime types.

Using Error Codes

In above example, we just checked whether there has been any error in uploading. We can give more specific error messages if we checked the error code.

if ($_FILES['filePhoto']['error'] == UPLOAD_ERR_PARTIAL) {
    $error = 'Partial update! Full file was not uploaded';

Above check will see whether the file was partially uploaded. You can also use corresponding integer values for error codes. For an example value of this error code is 3. But it’s more meaningful to use error codes themselves. You can check available error codes in PHP manual.


You can place a hidden field before the file upload field with the name MAX_FILE_SIZE to set UPLOAD_ERR_FORM_SIZE error code. Its value should be maximum allowed file size in bytes.

<input type="hidden" name="MAX_FILE_SIZE" value="51200" />
Photo: <input type="file" name="filePhoto" />

So, in our case, if a user uploaded a file larger than 50KB, the error code UPLOAD_ERR_FORM_SIZE will be set. This hidden field is just another hidden field and act as a clue to this error code. PHP manual describes this field as follows,

The MAX_FILE_SIZE hidden field (measured in bytes) must precede the file input field, and its value is the maximum file size accepted by PHP. This form element should always be used as it saves users the trouble of waiting for a big file being transferred only to find that it was too large and the transfer failed.

But currently no web browser by default takes this as a directive and prevents users uploading files larger than the specified size, files will be always uploaded to the server. However, it would be good to keep this field since there is no harm and in case it would be supported in the future or by an extension.

Uploading Multiple Files

Like in textual form fields, you can upload multiple files with same name and get their details in arrays. However the way arrays are set is bit different.

Photo1: <input type="file" name="filePhoto[]" /><br />
Photo2: <input type="file" name="filePhoto[]" /><br />
Photo3: <input type="file" name="filePhoto[]" /><br />

Once you would have fields like above, you would expect to access name of first file like below.


But instead of populating sub arrays for each uploaded file, PHP groups file criteria like name into sub array. So, you would have to access name of first file as below.


Try to understand this behavior by changing file-upload.html to include multiple file fields and file-upload.php to have var_export() function for $_FILES.

If large files are expected to be uploaded, having multiple file fields can lead to timeout errors. Keep that in mind when you create your PHP application. You can integrate Ajax to address this issue.

Security Concerns

Form fields are a major medium used for security attacks. The concern is even higher with file upload fields since possibility of uploading malicious files. One precaution used by many applications is allowing only logged in users to upload files.

Where to Head from Here...
Share with Your Peers...

We Value Your Feedback...

We love to hear what you think about this article. Please provide your opinion, suggestions and improvements using following form. Note that submitted feedback is not displayed but we will get back to you if it needs a reply.