Secure File Upload with PHP

Download Source

PHP makes uploading files easy. You can upload any type of file to your Web server. But with ease comes danger and you should be careful when allowing file uploads.

In spite of security issues that should be addressed before enabling file uploads, the actual mechanisms to allow this are straight forward. In this tutorial we will consider how to upload files to some directory on your Web server. We will also discuss security issues concerned with the file uploading.

The HTML Form

Before you can use PHP to manage your uploads, you need first construct an HTML form as an interface for a user to upload his file. Have a look at the example below and save this HTML code as index.php.

  <form enctype="multipart/form-data" action="upload.php" method="post">
    <input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
    Choose a file to upload: <input name="uploaded_file" type="file" />
    <input type="submit" value="Upload" />

There are some rules you need to follow when constructing your HTML form. First, make sure that the form uses the POST method. Second, the form needs the following attribute: enctype=”multipart/form-data”. It specifies which content-type to use when submitting information back to server. Without these requirements, your file upload will not work.

Another thing to notice is the hidden form field named MAX_FILE_SIZE. Some web browsers actually pick up on this field and will not allow the user to upload a file bigger than this number (in bytes). You should set this value to coincide with the maximum upload size that is set in your php.ini file. It is set with the upload_max_filesize directive and the default is 2MB. But it still cannot ensure that your script won’t be handed a file of a larger size. The danger is that an attacker will try to send you several large files in one request and fill up the file system in which PHP stores the decoded files. Set the post_max_size directive in your php.ini file to the maximum size that you want (must be greater than upload_max_filesize). The default is 10MB. This directive controls the maximum size of all the POST data allowed in a single request. Also make sure that file_uploads inside your php.ini file is set to On.

At least, have a look at the input tag attribute: type=”file”. It is used to designate the input element as a file select control. This provides a place for the URI of a file to be typed and a “Browse” button which can be used as an alternative to typing the URI.

After the user enters the URI of a file and clicks the Submit button the copy of the file will be sent to the server and the user will be redirected to upload.php. This PHP file will process the form data.

Back to top

Processing the Form Data (PHP Code)

When the file was uploaded, PHP created a temporary copy of the file, and built the superglobal $_FILES array containing information about the file. For each file, there are five pieces of data. We had named our upload field ‘uploaded_file’, so the following data would exist:

  • $_FILES[“uploaded_file”][“name”] the original name of the file uploaded from the user’s machine
  • $_FILES[“uploaded_file”][“type”] the MIME type of the uploaded file (if the browser provided the type)
  • $_FILES[“uploaded_file”][“size”] the size of the uploaded file in bytes
  • $_FILES[“uploaded_file”][“tmp_name”] the location in which the file is temporarily stored on the server
  • $_FILES[“uploaded_file”][“error”] an error code resulting from the file upload

The example below accepts an uploaded file and saves it in the upload directory. It allows to upload only JPEG images under 350Kb. The code, itself, is rather clear, but we will give a little explanation. Have a look at the example and save this PHP code as upload.php.

//–°heck that we have a file
if((!empty($_FILES["uploaded_file"])) && ($_FILES['uploaded_file']['error'] == 0)) {
  //Check if the file is JPEG image and it's size is less than 350Kb
  $filename = basename($_FILES['uploaded_file']['name']);
  $ext = substr($filename, strrpos($filename, '.') + 1);
  if (($ext == "jpg") && ($_FILES["uploaded_file"]["type"] == "image/jpeg") && 
    ($_FILES["uploaded_file"]["size"] < 350000)) {
    //Determine the path to which we want to save this file
      $newname = dirname(__FILE__).'/upload/'.$filename;
      //Check if the file with the same name is already exists on the server
      if (!file_exists($newname)) {
        //Attempt to move the uploaded file to it's new place
        if ((move_uploaded_file($_FILES['uploaded_file']['tmp_name'],$newname))) {
           echo "It's done! The file has been saved as: ".$newname;
        } else {
           echo "Error: A problem occurred during file upload!";
      } else {
         echo "Error: File ".$_FILES["uploaded_file"]["name"]." already exists";
  } else {
     echo "Error: Only .jpg images under 350Kb are accepted for upload";
} else {
 echo "Error: No file uploaded";

Before you do anything with the uploaded file you need to determine whether a file was really uploaded. After that we check if the uploaded file is JPEG image and its size is less than 350Kb. Next we determine the path to which we want to save this file and check whether there is already a file with such name on the server. When all checks are passed we copy the file to a permanent location using the move_upload_file() function. This function also confirms that the file you’re about to process is a legitimate file resulting from a user upload. If the file is uploaded successfully then the corresponding message will appear. 

Note: Be sure that PHP has permission to read and write to the directory in which temporary files are saved and the location in which you’re trying to copy the file.

This example is rather simple and its propose is to demonstrate you how to upload files using PHP. For example, you can add new conditions and allow to upload GIF and PNG images, or any other kind of files that you want. If you are unfamiliar with PHP this tutorial may be a good place to start.

Back to top



Leave a Reply

Your email address will not be published.