- Predefined Variables
- A Script to Acquire User Input
- Accessing Form Input with User Defined Arrays
- Accessing Form Input with Built-In Arrays
- Distinguishing Between GET and POST Transactions
- Combining HTML and PHP Code on a Single Page
- Using Hidden Fields to Save State
- Redirecting the User
- File Upload Forms and Scripts
- Summary
- Q&A
- Workshop
File Upload Forms and Scripts
So far we've looked at simple form input. Browsers Netscape 2 or better and Internet Explorer 4 or better all support file uploads, and so, of course, does PHP. In this section, you will examine the features that PHP makes available to deal with this kind of input.
First, we need to create the HTML. HTML forms that include file upload fields must include an ENCTYPE argument:
ENCTYPE="multipart/form-data"
PHP also works with an optional hidden field that can be inserted before the file upload field. This should be called MAX_FILE_SIZE and should have a value representing the maximum size in bytes of the file that you are 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 2 megabytes. The MAX_FILE_SIZE field will be obeyed at the browser's discretion, so you should rely upon the php.ini setting to cap unreasonable uploads. After the MAX_FILE_SIZE field has been entered, you are 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 enctype="multipart/form-data" method="POST"> 7: <input type="hidden" name="MAX_FILE_SIZE" value="51200"> 8: <input type="file" name="fupload"><br> 9: <input type="submit" value="upload!"> 10: </form> 11: </body> 12: </html>
Notice that once again this form calls the page that contains it. This is because we are going to add some PHP code to handle the uploaded file. We limited file uploads to 50KB on line 7 and named our upload field "fupload" on line 8. As you might expect, this name will soon become important.
When a file is successfully uploaded, it is given a unique name and stored in a temporary directory. On Unix systems the default temporary directory is /tmp, but you can set it with the upload_tmp_dir directive in php.ini.
Information about the uploaded file will become available to you in the $HTTP_POST_ FILES array which will be indexed by the names of each upload field in the form. The corresponding value for each of these keys will itself be an associative array. These fields are described in Table 9.2.
Table 9.2 File Upload Global Variables
Element |
Contains |
Example |
$HTTP_POST_FILES['fupload']['name'] |
Name of uploaded file |
test.gif |
$HTTP_POST_FILES['fupload']['tmp_name'] |
Path to temporary file |
/tmp/phprDfZvN |
$HTTP_POST_FILES['fupload']['size'] |
Size (in bytes) of uploaded file |
6835 |
$HTTP_POST_FILES['fupload']['type'] |
Mime type of uploaded file(where given by client) |
image/gif |
Armed with this information, we can write a quick and dirty script that displays information about uploaded files (see Listing 9.14). If the uploaded file is in GIF format, the script will even attempt to display it.
Listing 9.14 A File Upload Script
1: <html> 2: <head> 3: <title>Listing 9.14 A file upload script</title> 4: </head> 5: <?php 6: $file_dir = "/home/corrdev/htdocs/php24/scrap/uploads"; 7: $file_url = "http://corros.colo.hosteurope.com/dev/php24/scrap/uploads"; 8: 9: foreach( $HTTP_POST_FILES as $file_name => $file_array ) { 10: print "path: ".$file_array['tmp_name']."<br>\n"; 11: print "name: ".$file_array['name']."<br>\n"; 12: print "type: ".$file_array['type']."<br>\n"; 13: print "size: ".$file_array['size']."<br>\n"; 14: 15: if ( is_uploaded_file( $file_array['tmp_name'] ) 16: && $file_array['type'] == "image/gif" ) { 17: move_uploaded_file( $file_array['tmp_name'], "$file_dir/$file_name") 18: or die ("Couldn't copy"); 19: print "<img src=\"$file_url/$file_name\"><p>\n\n"; 20: } 21: } 22: 23: ?> 24: <body> 25: <form enctype="multipart/form-data" method="POST"> 26: <input type="hidden" name="MAX_FILE_SIZE" value="51200"> 27: <input type="file" name="fupload"><br> 28: <input type="submit" value="Send file!"> 29: </form> 30: </body> 31: </html>
In Listing 9.14, we first create the $file_dir and $file_url variables on lines 6 and 7 to store path information. Then we use a foreach statement to loop through every element in the $HTTP_POST_FILES array on line 9. This will be empty the first time the page is loaded, so nothing in the loop will be executed and our script will default to writing the upload form.
Once the form has been submitted the $HTTP_POST_FILES array will be populated. We are using a loop rather than an if statement in order to make our script capable of scaling to deal with multiple uploads on the same page. The foreach loop on line 9 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.
To move the uploaded file to a directory within our web space, we need to run a couple of checks first. We are only dealing with GIF files in this example so test the mime type on line 16.
Also, use a new function to verify the file on line 15. The is_uploaded_file() function was re-introduced with PHP 4.03. It 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, copy the file from its temporary home to a new directory on line 17. We use another function, move_uploaded_file() for this purpose. This will copy a file from one place to another, first performing the same security checks as those performed by is_uploaded_file(). move_uploaded_file() requires a path to the source file and a path to the destination. It will return true if the move was successful and false if the file was not a valid upload file, or if it could not be found.
CAUTION
Beware of the names of uploaded files. Operating systems such as MacOS 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. It is therefore a good idea to filter file names. You can learn more about techniques for testing and checking strings in Hour 17 "Working with Strings" and Hour 18 "Working with Regular Expressions".
When we created the $file_dir variable on line 6 to store the file path to our upload directory, we also created a variable called $file_url on line 7 to store the URL of the same directory. We wrap up the script by writing an HTML image element that references our newly written image.