Basic File Uploading Using PHP

By  on  

I create a lot of websites that allow administrators to upload files to their own website. Since allowing user customization has become more and more important on websites these days, I thought I'd share how easy it is to handle file uploads in PHP.

The XHTML Form

<form action="accept-file.php" method="post" enctype="multipart/form-data">
	Your Photo: <input type="file" name="photo" size="25" />
	<input type="submit" name="submit" value="Submit" />
</form>

You'll need to use the multipart/form-data value for the form's enctype property. You'll also obviously need at least one input element of the file type. The form's action tag must provide a URL which points the a file containing the piece of PHP below.

The PHP

//if they DID upload a file...
if($_FILES['photo']['name'])
{
	//if no errors...
	if(!$_FILES['photo']['error'])
	{
		//now is the time to modify the future file name and validate the file
		$new_file_name = strtolower($_FILES['photo']['tmp_name']); //rename file
		if($_FILES['photo']['size'] > (1024000)) //can't be larger than 1 MB
		{
			$valid_file = false;
			$message = 'Oops!  Your file\'s size is to large.';
		}
		
		//if the file has passed the test
		if($valid_file)
		{
			//move it to where we want it to be
			move_uploaded_file($_FILES['photo']['tmp_name'], 'uploads/'.$new_file_name);
			$message = 'Congratulations!  Your file was accepted.';
		}
	}
	//if there is an error...
	else
	{
		//set that to be the returned message
		$message = 'Ooops!  Your upload triggered the following error:  '.$_FILES['photo']['error'];
	}
}

//you get the following information for each file:
$_FILES['field_name']['name']
$_FILES['field_name']['size']
$_FILES['field_name']['type']
$_FILES['field_name']['tmp_name']

My commenting in the PHP above outlines the way the process works, so I'll just mention a few notes about file uploads in PHP:

  • Many shared hosting servers allow a very low maximum file upload size. If you plan on accepting larger files, you should consider a dedicated or virtual dedicated server.
  • To adjust the file upload size in PHP, modify the php.ini file's "upload_max_filesize" value. You can also adjust this value using PHP's .ini_set() function.
  • The file upload counts towards the hosting environment's $_POST size, so you may need to increase the php.ini file's post_max_size value.
  • Be sure to do a lot of file validation when allowing users to upload files. How horrible would it be to allow a user to upload a .exe file to your server? They could do horrible things on the server.

Recent Features

  • By
    Conquering Impostor Syndrome

    Two years ago I documented my struggles with Imposter Syndrome and the response was immense.  I received messages of support and commiseration from new web developers, veteran engineers, and even persons of all experience levels in other professions.  I've even caught myself reading the post...

  • By
    An Interview with Eric Meyer

    Your early CSS books were instrumental in pushing my love for front end technologies. What was it about CSS that you fell in love with and drove you to write about it? At first blush, it was the simplicity of it as compared to the table-and-spacer...

Incredible Demos

  • By
    Dynamic Waveform Visualizations with wavesurfer.js

    Waveform images are an awesome addition to boring audio widgets.  They can be functional as well as aesthetically pleasing, allowing users to navigate audio visually.  I recently found wavesurfer.js, an amazing waveform image utility that uses to Web Audio API to create super customizable...

  • By
    Unicode CSS Classes

    CSS class name structure and consistency is really important; some developers camelcase classnames, others use dashes, and others use underscores.  One thing I've learned when toying around by HTML and CSS class names is that you can actually use unicode symbols and icons as classnames.

Discussion

  1. @Binny: Great work!

  2. Greetings!

    I’m a big admirer of your site David, you always get the important code or meaning across without distracting filler. It’s great :)

    A couple of points regarding the above PHP upload script:

    i) $valid_file is never declared true, so I added the following just before the 'if($valid_file)'.

    else { $valid_file = true; }
    

    ii) I was unable to get it working with strtolower and the uploads/ directory but this worked for me:

    $currentdir = getcwd();
    $target = $currentdir .'/uploads/' . basename($_FILES['photo']['name']);
    move_uploaded_file($_FILES['photo']['tmp_name'], $target);
    

    Thanks again, have fun :D

    • Dave,
      Thanks for your points man! 2nd point helped me big time!

    • This comment particularly was really helpful. Great blog article and great tips from the audience. Got the file upload working. Super cool!

      Anyone have any best practices for testing against malicious uploads or “fake” images?

  3. hjhgjhgj

    //if they DID upload a file…
    if($_FILES[‘photo’][‘name’])
    {
    //if no errors…
    if(!$_FILES[‘photo’][‘error’])
    {
    //now is the time to modify the future file name and validate the file
    $new_file_name = strtolower($_FILES[‘photo’][‘tmp_name’]); //rename file
    if($_FILES[‘photo’][‘size’] > (1024000)) //can’t be larger than 1 MB
    {
    $valid_file = false;
    $message = ‘Oops! Your file\’s size is to large.’;
    }

    //if the file has passed the test
    if($valid_file)
    {
    //move it to where we want it to be
    move_uploaded_file($_FILES[‘photo’][‘tmp_name’], ‘uploads/’.$new_file_name);
    $message = ‘Congratulations! Your file was accepted.’;
    }
    }
    //if there is an error…
    else
    {
    //set that to be the returned message
    $message = ‘Ooops! Your upload triggered the following error: ‘.$_FILES[‘photo’][‘error’];
    }
    }

    //you get the following information for each file:
    $_FILES[‘field_name’][‘name’]
    $_FILES[‘field_name’][‘size’]
    $_FILES[‘field_name’][‘type’]
    $_FILES[‘field_name’][‘tmp_name’]

  4. $allowedExts = array(“jpg”, “jpeg”, “gif”, “png”);
    $extension = end(explode(“.”, $_FILES[“file”][“name”]));
    if ((($_FILES[“file”][“type”] == “image/gif”)
    || ($_FILES[“file”][“type”] == “image/jpeg”)
    || ($_FILES[“file”][“type”] == “image/png”)
    || ($_FILES[“file”][“type”] == “image/pjpeg”))
    && ($_FILES[“file”][“size”] 0)
    {
    $msg = “Error while upload!!! Return Code: ” . $_FILES[“file”][“error”];
    }
    else
    {
    $downloadspath = MAIN_PATH . “downloads/”;
    $filename = $_FILES[“file”][“name”];
    $filetype = $_FILES[“file”][“type”];
    $filesize = ($_FILES[“file”][“size”] / 1024) . ” kB”;

    if (file_exists(“downloads/” . $_FILES[“file”][“name”]))
    {
    echo $_FILES[“file”][“name”] . ” already exists. “;
    }
    else
    {
    move_uploaded_file($_FILES[“file”][“tmp_name”], $downloadspath . $_FILES[“file”][“name”]);
    echo “Stored in: “. MAIN_PATH . “downloads/” . $_FILES[“file”][“name”];
    }
    $q = “INSERT INTO downloads (title ,filename ,filesize, filetype )VALUES (‘$filetitle’, ‘$filename’, ‘$filesize’, ‘$filetype’)”;
    mysql_query($q);
    }

    }
    else
    {
    $msg = “Invalid file!!!”;
    }

  5. Anna

    great tutorial however after i upload my files i can’t access my images
    why is this?
    help please

  6. Great tutorial. Thanks for your work. It helped me a lot to learn about PHP file uploading process very easily. Specially the commenting inside the code is so cool.

  7. lummy

    tried using the code above though it works on my localhost but it’s not working on the online server, especially the move_ uploaded_ file statement. the file is not saving to the folder i specified.

  8. lummy

    tried using the code above though it works on my localhost but it’s not working on the online server, especially the move_ uploaded_ file statement. the file is not saving to the folder i specified.
    this is the code
    <?php
    echo "”;
    echo “Client Filename:
    ” . $_FILES[“fileToUpload”][“name”] . “”;
    echo “File Type:
    ” . $_FILES[“fileToUpload”][“type”] . “”;
    echo “File Size:
    ” . ($_FILES[“fileToUpload”][“size”] / 1024) . ” Kb”;
    echo “Name of Temp File:
    ” . $_FILES[“fileToUpload”][“tmp_name”] . “”;
    echo “”; move_uploaded_file($_FILES[“fileToUpload”][“tmp_name”], “user/” . $_FILES[“fileToUpload”][“name”]); ?>

  9. Youssef Ahmad Subehi

    i think you should correct this code
    move_uploaded_file($_FILES[‘photo’][‘tmp_name’], ‘uploads/’.$new_file_name);
    and make it
    move_uploaded_file($_FILES[‘photo’][‘name’], ‘uploads/’.$new_file_name);

  10. Nishanth

    Hello
    I am getting error here if($_FILES['photo']['size'] > (1024000))

    From this line the entair coad is displaying
    can any one help me

  11. snag

    hello
    help me to sort out my problem
    i can upload image in localhost but not able to upload in hosted server,
    output of print_r($_FILES) is

    Array ( [imageup] => Array ( [name] => IMG00054.jpg [type] => [tmp_name] => [error] => 1 [size] => 0 ) )
    
  12. Sonny Nguyen
    $new_file_name = strtolower($_FILES['photo']['tmp_name']);
    

    Should be

    $new_file_name = strtolower($_FILES['photo']['name']);
    
  13. Shawn

    Easy explaination there is also a short and easy tutorial of how to upload images to database and in server on TalkersCode.com http://talkerscode.com/webtricks/upload%20image%20to%20database%20and%20server%20using%20HTML,PHP%20and%20MySQL.php

  14. Manish

    Well written, but when i read your code and tried to execute code, found a mistake in one place, you should use $_FILES['photo']['name'] instead tmp_name when you used to set $new_file_name first time. Thanks for posting

  15. Also to prevent diacritics that can make some truble, you can use the function bellow:

    $title = mysql_real_escape_string($_POST['titlui']);
    $unwanted_array = array(     'ă'=>'a', 'Ă'=>'A', 'ș'=>'s', 'Ș'=>'S', 'ț'=>'t', 'Ț'=>'T', 'Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
                                'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',
                                'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
                                'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
                                'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y' );
    $title = strtr( $title, $unwanted_array );
    
  16. Cyrus

    Awesome, well written tutorial man, thanks a lot

  17. Christopher Dando

    Hi David, thanks for the tutorial, it’s really good. it was working for me for a while, but suddenly

    if ($_FILES['photo']['name']) {

    does not detect the file, matter what I try. in my error.log I get the error ‘Undefined index’. any ideas?

    • Did you try using isset($_FILES['photo']['name'])? The problem happens because the name field is not set before the form is submitted.

    • The variable photo is the name="" attribute on your input[type="file"] HTML element. So it is likely that you changed the name of your element, thus $_FILES cannot find your item. Change photo to the name="something" name of your element, or add photo as in,

  18. $_FILES['photo']['tmp_name] gives a path which can’t be used properly to create the final file name in move_uploaded_to.

  19. fercho

    This example helped me a lot thanks man!

  20. I found this file upload functionality as a nightmare when I start my web development career. I could wish this article would have been earlier.

    Thanks David :)

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!