Section 5.8. File Uploads


5.8. File Uploads

We haven't yet covered one type of input-uploading files. You can use the file upload feature of PHP to upload images or related materials, for example. Because the browser needs to do a little bit more than just send a POST with the relevant data, you need to use a specially crafted form for file uploads. Here is an example of such a special form:

 <form enctype="multipart/form-data" action="handle_img.php" method="post">      <input type="hidden" name="MAX_FILE_SIZE" value="16000" />      Send this file: <input name="book_image" type="file" /><br />      <input type="submit" value="Upload" /> </form> 

The differences between file upload forms and normal forms are bold in the code listing. First, an enctype attribute, included in the form tag, instructs the browser to send a different type of POST request. Actually, it's a normal POST request, except the body containing the encoded files (and other form fields) is completely different. Instead of the simple field=var&field2=var2 syntax, something resembling a "text and HTML" email is sent in the body, with each part being a form field.

The file upload field itself is the type file, which displays an input field and a browse button that allows a user to browse through the file system to find a file. The text on the browse button can't be changed, so it is usually localized. (Mozilla in English uses "Browse," IE in Dutch uses "Bladeren," and so on.) The hidden input field sends a MAX_FILE_SIZE to the browser, setting the maximum allowable size of the file being uploaded. However, most browsers ignore this extra field, so it's up to you in the handler script to accept or deny the file.

5.8.1. Handling the Incoming Uploaded File

The $_FILES array contains an array of information about each file that is uploaded. The handler script can access the information using the name of the uploaded file as the key. The $_FILES['book_image'] variable contains the following information for the uploaded file.

Key

Value

Description

name

string(8) "p5pp.jpg"

The original name of the file on the file system of the user who uploaded it.

type

string(10) "image/jpeg"

The MIME type of the file. For a JPG image, this can be either image/jpeg or image/pjpeg and all other types have their dedicated MIME type.

tmp_name

string(14) "/tmp/phpyEXxWp"

The temporary file name on the server's file system. PHP will clean up after the request has finished, so you are required to do something with it inside the script that handles the request (either delete or move it).

error

int(0)

The error code. See the next paragraph for an explanation.

size

int(2045)

The size in bytes of the uploaded file.


A few possible errors can occur during a file upload. Most errors relate to the size of the uploaded file. Each error code has an associated constant. The following table shows the error conditions.

#

Constant

Description

0

UPLOAD_ERR_OK

The file was uploaded successfully and no errors occurred.

1

UPLOAD_ERR_INI_SIZE

The size of the uploaded files exceeded the value of the upload_max_file setting from php.ini.

2

UPLOAD_ERR_FORM_SIZE

The size of the uploaded files exceeded the value of the special form field MAX_FILE_SIZE. Because users can easily fake the size, you cannot rely on this one, and you always have to check the sizes yourself in the script by using $_FILES ['book_image']['size'];.

3

UPLOAD_ERR_PARTIAL

There was a problem uploading the file because only a partial file was received.

4

UPLOAD_ERR_NO_FILE

There was no file uploaded at all because the user did not select any in the upload form. This is not always an error; this field might not be required.


After learning all this theory, we now examine the script that uploads a file. In this script, we check if the size is acceptable (we don't want more than 50KB for the uploaded images) and if the uploaded file is of the correct type (we only want JPEG and PNG files). Of course, we also check the error codes shown in the previous table and use the correct way of moving it to our uploaded images directory:

 <?php      /* configuration settings */      $max_photo_size = 50000;      $upload_required = true; 

We require a file not greater than 50KB to be uploaded:

 $upload_page = 'index.php'; $upload_dir = '/home/httpd/html/fileupl/'; 

The upload directory is the name of the directory that is the final destination for the uploaded file. This directory needs to be writeable to the server's user (or group). For example, you can issue the following commands to make the directory writeable (as root):

 # chgrp nogroup /home/httpd/html/fileupl # chmod g+wrx /home/httpd/html/fileupl 

In our situation, the web server runs as user nouser and with group nogroup. If you want to know under which user and group your web server runs, you can find out with the following command

 # ps axo user,fsgroup,command | grep httpd      $err_msg = false;      do { 

Tip

We "misuse" a do...while block here as a poor man's goto. By using while(0) at the end, the code block always runs only once, and you can jump to the end of it by using break.


 /* Does the file field even exist? */ if (!isset ($_FILES['book_image'])) {     $err_msg = 'The form was not sent in completely.';     break; 

Perhaps somebody played tricks and didn't use the form we provided. Thus, we need to check whether the posted form actually contains our book_image field. The previous code sets the error message to a not-false value. We check for this in later logic:

 } else {     $book_image = $_FILES['book_image']; } /* We check for all possible error codes wemight get */ switch ($book_image['error']) {     case UPLOAD_ERR_INI_SIZE:         $err_msg = 'The size of the image is too large, '.             "it can not be more than $max_photo_size bytes.";         break 2; 

This error occurs when the uploaded file(s) exceed the configured php.ini setting upload_max_filesize and defaults to 2MB for the collected size of all uploaded files. Three other php.ini settings are important. One is post_max_size, which controls the maximum allowed size of a POST request (it defaults to 8MB). The second is file_uploads, which determines whether scripts may use remote file names or not at all (it defaults to on). The last setting affecting file uploads is upload_tmp_dir, which specifies the temporary directory where files are uploaded (it defaults to /tmp on UNIX-like operating systems or the configured temporary directory on Windows).

 case UPLOAD_ERR_PARTIAL:    $err_msg = 'An error ocurred while uploading the file, '.       "please <a href='{$upload_page}'>try again</a>.";     break 2; 

If the size of the uploaded file did not match the header's advertised size, the problem can be caused by a network connection that suddenly broke. For example:

 case UPLOAD_ERR_NO_FILE:    if ($upload_required) {       $err_msg = 'You did not select a file to be uploaded, '.           "please do so <a href='{$upload_page}'>here</a>.";       break 2;    }    break 2; 

We only issue an error if we require a file to be uploaded. Remember that we set the Boolean variable $upload_required at the top of our script to true:

 case UPLOAD_ERR_FORM_SIZE:    $err_msg = 'The size was too large according to '.        'the MAX_FILE_SIZE hidden field in the upload form.'; case UPLOAD_ERR_OK:    if ($book_image['size'] > $max_photo_size) {       $err_msg = 'The size of the image is too large, '.       "it can not be more than $max_photo_size bytes.";    }    break 2; 

Because we cannot rely on the user-supplied MAX_FILE_SIZE, we always need to check for the size ourselves. UPLOAD_ERR_OK is similar, except that the image will not be available in the temporary directory if it was larger than the MAX_FILE_SIZE:

 default:    $err_msg = "An unknown error occurred, ".        "please try again <a href='{$upload_page}'>here</a>."; } 

We should never receive an unknown error, but it is good practice to build in a case for this. Also, if another error type is added in newer PHP versions, your script won't break:

 /* Know we check for the mime type to be correct, we allow  * JPEG and PNG images */ if (!in_array(     $book_image['type'],     array ('image/jpeg', 'image/pjpeg', 'image/png') )) {     $err_msg = "You need to upload a PNG or JPEG image, ".        "please do so <a href='{$upload_page}'>here</a>.";     break; } 

With this code, we check whether to accept the file by looking at its MIME type. Note that some browsers might do things differently than others, so it's good to test all browsers and see what MIME type they use for specific files.

Tip

On http://www.webmaster-toolkit.com/mime-types.shtml, you can find an extensive list of MIME types.


 } while (0); /* If no error occurred we move the file to our upload directory */ if (!$err_msg) {     if (!@move_uploaded_file(         $book_image['tmp_name'],         $upload_dir . $book_image['name']     )) {         $err_msg = "Error moving the file to its destination, ".             "please try again <a href='{$upload_page}'>here</a>.";     } } ?> 

We use the "special" function move_uploaded_file() to move the file to its final destination. This function checks whether the file is really an uploaded file and whether the form was tricked into thinking the temporary file is something other than the file we specified, such as /etc/passwd. The function is_uploaded_file() returns true if the file is an uploaded file or false if it is not.

 <html> <head><title>Upload handler</title> <body> <?php         if ($err_msg) {         echo $err_msg;         } else { ?> <img src='/books/1/76/1/html/2/<?php echo $book_image['name']; ?>'/> <?php     } ?> </body> </html> 

We echo the error message in the body of the script in case there was an error uploading the file. (Remember that we initialized it to false at the top of the script.) In case the file upload succeeded, we construct an <img /> tag to display the uploaded image on our resulting page.

Tip

If you want to add the width and height attributes to the <img /> tag, you can use the imagesize() function to do so.


For more information about file uploading, see "The PHP Manual" at http://www.php.net/manual/en/features.file-upload.php.



    PHP 5 Power Programming
    PHP 5 Power Programming
    ISBN: 013147149X
    EAN: 2147483647
    Year: 2003
    Pages: 240

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net