Handling file uploads

bool move_uploaded_file ( string filename, string destination)

It might be that you want visitors to upload pictures for a member biography page, enclose attachments to forum messages, or just share files on a public download area - the ability to handle file uploads can be a great addition to web sites.

The basis for file uploads lies in a special variety of HTML input element, "file", which brings up a file selection dialog in most browsers that allows your visitor to select a file for uploading. You can include this element in a HTML form just like you would any other element - web browsers render it as a text box and a "select" (or "browse") button. When your form is submitted, it will automatically send with it the file.

Here is an example HTML form (save it as upload1.php) that allows users to select a file for uploading to your server. Note that we specify "enctype" in our form in order that our file be transmitted properly, and that the action property of the form is set to point to upload2.php, which we will look at in a moment.

<form enctype="multipart/form-data" method="post" action="upload2.php">
    Send this file: <input name="userfile" type="file" /><br />
    <input type="submit" value="Send File" />

You can see our new input file element in action - note that we give it the name "userfile". Now, here is the accompanying PHP script, upload2.php, which prints out a little information about the file just uploaded from upload1.php:

    print "Received {$_FILES['userfile']['name']} - its size is {$_FILES['userfile']['size']}";

PHP pre-sets variables for you with regards to the file just uploaded using a superglobal variable, $_FILES, to hold them. Each file uploaded is placed into the $_FILES superglobal array in the form of another array made up of information about the file itself - so we have an array within an array (a multidimensional array).

If we had two files - fileone and filetwo - rather than just 'userfile', PHP would put two arrays into $_FILES, each containing the name, size, and other information about fileone and filetwo respectively. As you can see above, PHP sets 'name' and 'size' to let you read the original filename given by the user, and the size of the file sent. It also sets 'tmp_name' to give you the name the file has on your server (might be something like /tmp/tmp000), and also 'type', which gives you the MIME type of the uploaded file (e.g. image/png) if it was provided by the uploading browser.

Give your uploading script a try in your web browser - see if you can modify the script yourself to check whether your browser sends a MIME type or not. If you find files over a certain size aren't being uploaded properly, you may find you need to increase a setting in your php.ini file, "upload_max_filesize".

Now that we are able to upload a file and read out information about, let's try something more useful - how to put the uploaded file in a place you choose.

PHP makes this particularly easy through the move_uploaded_file() function. move_uploaded_file() takes two filenames as its parameters, and returns false if the file you tried to move was either not sent by HTTP upload (perhaps your user was trying to fool your script into touching /etc/passwd) or if it couldn't be moved (perhaps due to permissions problems).

The first parameter should be the name of the uploaded file you wish to work with. This corresponds to $_FILES['userfile']['tmp_name'] if you are using 'userfile' as the form element in your upload HTML page. The second parameter is the name of the filename you want the uploaded file to be moved to. If all goes well, PHP returns true, and the file will be where you expect it. Let's take a look at the whole operation in action:

    if (move_uploaded_file($_FILES['userfile']['tmp_name'], "/place/for/file")) {
        print "Received {$_FILES['userfile']['name']} - its size is {$_FILES['userfile']['size']}";
    } else {
        print "Upload failed!";

Note that you will need to edit /place/for/file to somewhere PHP has permission to copy files. As you can see, handling file uploads with PHP really couldn't be easier - a call to move_uploaded_file() checks security and does the copying work all for you.


Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Advanced file upload handling >>

Previous chapter: A working example: making a counter

Jump to:


Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.