[ Team LiB ] Previous Section Next Section

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 you can insert before the file upload field. It 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 2MB. The MAX_FILE_SIZE field is 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 is entered, you are ready to add the upload field itself. It is simply an input element with a type argument of "file". You can give it any name you want. Listing 10.11 brings all this work together into an HTML upload form.

Listing 10.11 A Simple File Upload Form
 1: <!DOCTYPE html PUBLIC
 2:     "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 10.11 A Simple File Upload Form</title>
 7: </head>
 8: <body>
 9: <form enctype="multipart/form-data"
10:    action="<?print $_SERVER['PHP_SELF']?>" method="post">
11: <p>
12: <input type="hidden" name="MAX_FILE_SIZE" value="102400" />
13: <input type="file" name="fupload" /><br/>
14: <input type="submit" value="upload!" />
15: </p>
16: </form>
17: </body>
18: </html>

Notice that once again, this form calls the page that contains it. We are going to add some PHP code to handle the uploaded file. We limited file uploads to 100KB on line 12 and named our upload field "fupload" on line 13. 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 superglobal $_FILES array, which will be indexed by the names of each upload field in the form. The corresponding value for each of these keys is itself an associative array. These fields are described in Table 10.2.

Table 10.2. $_FILE Elements

Element

Contains

Example

$ FILES['fupload']['name']

Name of uploaded file

test.gif

$_FILES['fupload']['tmp_name']

Path to temporary file

/tmp/phprDfZvN

$_FILES['fupload']['size']

Size (in bytes) of uploaded file

6835

$_FILES['fupload']['error']

An error code corresponding to a PHP constant

UPLOAD_ERR_FORM_SIZE

$_FILES['fupload']['type']

MIME type of uploaded file (where given by client)

image/gif

You can use the error element of an element in $_FILES to diagnose the reason for a failed upload. Assuming a file upload named 'fupload', we would find the error code in


$_FILES['fupload']['error]

Table 10.3 lists the possible error codes.

Table 10.3. $_FILE Error Constants

Constant Name

Value

Explanation

UPLOAD_ERR_OK

0

No problem

UPLOAD_ERR_INI_SIZE

1

File size exceeds php.ini limit set in upload_max_filesize

UPLOAD_ERR_FORM_SIZE

2

File size exceeds limit set in hidden element named MAX_FILE_SIZE

UPLOAD_ERR_PARTIAL

3

File only partially uploaded

UPLOAD_ERR_NO_FILE

4

File was not uploaded

Armed with this information, we can write a quick and dirty script that displays information about uploaded files (see Listing 10.12). If the uploaded file is in GIF format, the script will even attempt to display it.

Listing 10.12 A File Upload Script
 1: <!DOCTYPE html PUBLIC
 2:     "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 10.12 A File Upload Script</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: if ( isset( $_FILES['fupload'] ) ) {
12:
13:     print "name: ".     $_FILES['fupload']['name']       ."<br />";
14:     print "size: ".     $_FILES['fupload']['size'] ." bytes<br />";
15:     print "temp name: ".$_FILES['fupload']['tmp_name']   ."<br />";
16:     print "type: ".     $_FILES['fupload']['type']       ."<br />";
17:     print "error: ".    $_FILES['fupload']['error']      ."<br />";
18:
19:     if ( $_FILES['fupload']['type'] == "image/gif" ) {
20:
21:         $source = $_FILES['fupload']['tmp_name'];
22:         $target = "upload/".$_FILES['fupload']['name'];
23:         move_uploaded_file( $source, $target );// or die ("Couldn't copy");
24:         $size = getImageSize( $target );
25:
26:         $imgstr = "<p><img width=\"$size[0]\" height=\"$size[1]\" ";
27:         $imgstr .= "src=\"$target\" alt=\"uploaded image\" /></p>";
28:
29:         print $imgstr;
30:     }
31: }
32: ?>
33: </div>
34: <form enctype="multipart/form-data"
35:     action="<?php print $_SERVER['PHP_SELF']?>" method="post">
36: <p>
37: <input type="hidden" name="MAX_FILE_SIZE" value="102400" />
38: <input type="file" name="fupload" /><br/>
39: <input type="submit" value="upload!" />
40: </p>
41: </form>
42: </body>
43: </html>

In Listing 10.12, we first check that the $_FILES['fupload'] element exists. If so, we can assume that the user has at least attempted to upload a file. We output each of the elements of the $_FILES['fupload'] array on lines 13 to 17. We then test the $_FILES['fupload']['type'] element. If we are dealing with a GIF image file, we can go ahead and print an img element. To do so, we need to move the uploaded file away from its temporary location (stored in $_FILES['fupload']['tmp_name']) and to a directory in our Web space. We use a new function, move_uploaded_file(), to achieve this goal on line 23. move_uploaded_file() requires two arguments, a source and a destination, and moves one to the other. It is the safest way of working with uploaded files because it confirms that the source file referenced is an uploaded file and not a server file that should not be exposed to the world at large. Having moved the file to our Web space, we call another new function, getImageSize(). getImageSize() requires a path to an image and returns an array. The first two elements of the return array are the width and height of the image. We now have enough information to write out an img element, which we do on line 27.

Do Not Expect Sensible Filenames!

graphics/watchout_icon.gif

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. It is therefore a good idea to filter filenames. You can learn more about techniques for testing and checking strings in Hour 8, "Working with Strings," and Hour 18, "Working with Regular Expressions."


    [ Team LiB ] Previous Section Next Section