Working with File Uploads

So far, we've looked at simple form input. However, all popular Web browsers support file uploads, and so, of course, does PHP. In this section, you examine the features that PHP makes available to deal with this kind of input.

Information about the uploaded file becomes available to you in the $_FILES superglobal, which is indexed by the name of the upload field (or fields) in the form. The corresponding value for each of these keys is an associative array. These fields are described in Table 9.2, using fileupload as the name of the form field used for the upload.

Table 9.2. File Upload Global Variables





Original name of uploaded file



Path to temporary file



Size (in bytes) of uploaded file



MIME type of uploaded file (where given by client)


Keep these elements in the back of your mind for a moment, while we create the upload form in the next section.

Creating the File Upload Form

First, we must create the HTML form to handle the upload. HTML forms that include file upload fields must include an ENCTYPE argument:


PHP also works with an optional hidden field that can be inserted before the file upload field. This field must be called MAX_FILE_SIZE and should have a value representing the maximum size in bytes of the file that you're willing to accept. This size cannot override the maximum size set in the upload_max_filesize field in your php.ini file that defaults to 2MB. The MAX_FILE_SIZE field is obeyed at the browser's discretion, so you should rely on the php.ini setting to cap unreasonable uploads. After the MAX_FILE_SIZE field has been entered, you're ready to add the upload field itself. This is simply an INPUT element with a TYPE argument of "file". You can give it any name you want. Listing 9.13 brings all this together into an HTML upload form.

Listing 9.13 A Simple File Upload Form
  1: <html>
  2: <head>
  3: <title>Listing 9.13 A simple file upload form</title>
  4: </head>
  5: <body>
  6: <form action="listing9.14.php" enctype="multipart/form-data" method="POST">
  7: <input type="hidden" name="MAX_FILE_SIZE" value="51200">
  8: File to Upload: <input type="file" name="fileupload"><br><br>
  9: <input type="submit" value="upload!">
 10: </form>
 11: </body>
 12: </html>

As you can see, file uploads are limited to 50KB on line 7, and the name of the file upload field is fileupload, as shown on line 8. Save this listing in a text file called listing9.13.php, and place that file in your Web server document root. Use your Web browser to access this form and you should see something like Figure 9.9.

Figure 9.9. Form created by Listing 9.13.


This form calls the listing9.14.php script, which we create next.

Creating the File Upload Script

If you remember the information regarding the $_FILES superglobal, you have all the information you need to write a simple file upload script. This script is the backend for the form created in Listing 9.13.

Listing 9.14 A File Upload Script
  1: <html>
  2: <head>
  3: <title>Listing 9.14 A file upload script</title>
  4: </head>
  5: <body>
  6: <h1>File Upload Results</h1>
  7: <?php
  8: $file_dir = "/path/to/upload/directory";
 10: foreach($_FILES as $file_name => $file_array) {
 11:     print "path: ".$file_array['tmp_name']."<br>\n";
 12:     print "name: ".$file_array['name']."<br>\n";
 13:     print "type: ".$file_array['type']."<br>\n";
 14:     print "size: ".$file_array['size']."<br>\n";
 16:     if (is_uploaded_file($file_array['tmp_name'])) {
 17:         move_uploaded_file($file_array['tmp_name'],
 18:            "$file_dir/$file_array[name]") or die ("Couldn't copy");
 19:         print "file was moved!<br><br>";
 20:      }
 21: }
 22: ?>
 23: </body>
 24: </html>

In Listing 9.14, we first create the $file_dir variable on line 8 to store path information. This path should be one that exists on your system, and you must have write permissions for it.


The path used in line 8 is a Linux/Unix path. Windows users would use backslashes, such as \My Documents\.

Line 10 begins a foreach statement that loops through every element in the $_FILES array. A loop is used rather than an if statement to make our script capable of scaling to deal with multiple uploads on the same page. The foreach loop on line 10 stores the upload file's name in the $file_name variable and the file information in the $file_array variable. We can then output the information we have about the upload.

Before moving the uploaded file from its temporary position to the location specified in line 8, first check that it exists. We do so on line 16, using the is_uploaded_file() function. This function accepts a path to an uploaded file and returns true only if the file in question is a valid upload file. This function therefore enhances the security of your scripts.

Assuming that all is well, the file is copied from its temporary home to a new directory on lines 17 and 18. We use another function, move_uploaded_file(), for this purpose. This function copies a file from one place to another, first performing the same security checks as those performed by is_uploaded_file(). The move_uploaded_file() function requires a path to the source file and a path to the destination. It returns true if the move is successful and false if the file isn't a valid upload file or if the file couldn't be found.


Beware of the names of uploaded files. Operating systems such as Mac OS and Windows are pretty relaxed when it comes to file naming, so expect uploaded files to come complete with spaces, quotation marks, and all manner of other unexpected characters. Therefore, it's a good idea to filter filenames. You can learn more about techniques for testing and checking strings in Hour 13, "Working with Strings."

Put these lines into a text file called listing9.14.php, and place that file in your Web server document root. Use your Web browser to go back to the form, and try to upload a file. If successful, you should see something like Figure 9.10 in your browser.

Figure 9.10. Sample results from Listing 9.14.


    Part III: Getting Involved with the Code