Introduction
As Web pages move closer to becoming Web applications, the ability to transfer files in their entirety to the server has become a pressing issue. In this week's Code Gallery Spotlight, "ADMIN" shows how to upload files to the server through an HTML form and PHP with their contribution "File uploading".
Uploading, PHP and you
As Web pages have moved from static documents into dynamic database-driven applications, users are looking for the ability to upload data in the form of files. In today's article, we'll be looking at how files can be uploaded and then processed in PHP.
Let's assume that your Web site is devoted to a community of graphic artists from all backgrounds. As your site grew, you started devoting a section to displaying your members' works.
Until now, a member would send his or her contribution to an e-mail address listed on the Web site, and from there the image would be manually processed and added. With PHP 4, not only can your members upload images from the Web site directly, but also the majority of the processing that was done manually can now be automated. Here's how browser-based file uploading works:
How it works
Because of standard changes brought on by RFC1867, browsers such as Netscape 3.0+, Internet Explorer 4.0+ (or an upgraded version of 3.0) have the ability to upload a file during a form POST operation. To properly upload a file through a browser, we'll take a look at the HTML required before we actually get to the server-side processing through PHP 4.
The client-side HTML
In order to upload a file, a special type of HTML form is required to direct the browser. To begin, we'll need to add the ENCTYPE="multipart/form-data" attribute to the <FORM> tag, and then include a new "File" input type in our form. Here's an example of a basic HTML form used to upload a file:
...
<FORM ACTION="process.php" METHOD=POST
ENCTYPE="multipart/form-data">
<INPUT TYPE="file" NAME="myfile" SIZE=30>
<INPUT TYPE="submit" NAME="Upload File">
</FORM>
...
When the above is rendered in the browser the form will consist of a text box of size 30 with a button next to it and the button we created to submit the form entitled "Upload File".
- text box and the button next to it (usually labeled "Browse") are used to select the file on the local machine that the user would like to upload. Using this mechanism, the user then:
- provides a full path and filename to show where the file to be uploaded is located
- clicks the "Upload File" button to submit the file.
What happens when the file is "submitted"
In order to better understand this, let's take a look at the ENCTYPE attribute we specified in our FORM tag. By specifying ENCTYPE="multipart/form-data", we are telling the browser to send all of the information included with the form to the server in such a way that each separate "part" of the data is identified by its own MIME headers.
These MIME headers are then used on the server to separate the data into individual parts (and hence, individual files). Thankfully, PHP 4 handles all of the work of processing the posted form data for us, and saves us a lot of dirty work. In PHP 4, all we really need to be concerned with is processing the file.
Processing the file
Once the file has been uploaded, by default the server will store the file in the Web server's temporary storage directory. It will then execute the actual script that the form was POSTed to. When the script executes, it must process the file and move it to another location on the server before the script completes. Once the script has completed, the file will be deleted from the temporary directory, so it's important that it is moved to a new location if needed.
Note: Depending on the configuration of your server, the directory in which PHP temporarily stores uploaded files may change. To find out where PHP stores your uploaded files, run the phpinfo()
and check the settings of the upload_tmp_dir
setting.
Accessing the file from PHP
When PHP receives the file and creates it within the temporary upload directory, it sets up a number of global variables. These variables are accessible from within your script and contain a number of useful things in associative array form. The base name of these variables is $HTTP_POST_FILES
.
Within this array, a set of keys are created based on the name you assigned to the file input tag in your HTML (in the previous example, it was "myfile"). For argument's sake, assume that PHP received this name as the name of our <INPUT TYPE="FILE">
and created the following keys from them:
$HTTP_POST_FILES['myfile']['tmp_name']
-- Contains the full path and filename of the uploaded file as stored on the server.
$HTTP_POST_FILES['myfile']['name']
-- Contains the full path and filename of the uploaded file as stored on the client.
$HTTP_POST_FILES['myfile']['size']
-- Contains the size of the file in bytes
$HTTP_POST_FILES['myfile']['type']
-- Contains the MIME type information associated with the file (if any)
Please note that if multiple files are uploaded (using multiple names on the input tag) multiple base keys (for example, 'myfile') will be created. With these keys, we have all of the information we need to do any processing of the file(s) using the wide range of functions in PHP!
Final notes
Before we take a look at our example script, there are a few more useful bits of information that you should be aware of. Firstly, if an attempt to upload a file fails for any reason (and hence the file was not uploaded), the tmp_name key will contain "none". You can also control the maximum file size that PHP will accept as a file upload by placing a hidden field before the appropriate file input field entitled MAX_FILE_SIZE
with the maximum value (in bytes) of the file.
The script
Now that we have a feel for how PHP can be used to deal with uploading files, let's take a look at this week's Code Gallery Spotlight. This script will accept an uploaded file (assumed to be an image) and extract some information regarding the image (such as size), move it, and display the results to the user.
Step 1 - Determine action / display the HTML upload form
Because in our example everything is done (displaying and processing) from a single file, we need to determine the course of action PHP should take. In order to determine if we are processing an uploaded file, or presenting the form to upload a file, we need to see if the hidden value (named "action") exists as a posted PHP variable in the global array $HTTP_POST_VARS['action']
.
Code Flow
- Check for existence of $action
- If
$action
doesn't exist, display HTML form to upload a file
<?php if ($HTTP_POST_VARS['action']) { ?>
<!-- Code to process Uploaded File and Display -->
<!-- The HTML to display the results -->
?>
<BR><A HREF="<?php echo $PHP_SELF ?>">Back</A>
</FONT></P>
</BODY>
</HTML>
<?php } else { ?>
<HTML>
<HEAD>
<TITLE>File Upload</TITLE>
</HEAD>
<BODY BGCOLOR="WHITE" TEXT="BLACK">
<P><FONT FACE="Arial, Helvetica, sans-serif"><FONT SIZE="+1">File
Upload</FONT><BR><BR>
If your browser is upload-enabled, you will see "Browse" (Netscape,
Internet Explorer), or "..." (Opera) buttons below. Use them to
select files to upload, then click the "Upload" button. After the
files have been uploaded, you will see a results screen.<BR>
<FORM METHOD="POST" ENCTYPE="multipart/form-data"
ACTION="<?php echo $PHP_SELF;?>">
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="800000">
<INPUT TYPE="HIDDEN" NAME="action" VALUE="1">
File 1: <INPUT TYPE="FILE" NAME="file1" SIZE="30"><BR><BR>
<INPUT TYPE="SUBMIT" VALUE="Upload">
</FORM>
</FONT></P>
</BODY>
</HTML>
<?php } ?>
Step 2 - Process the uploaded File
Now that we have displayed the form to upload the file, and the user has selected the file to upload and submitted the request, PHP accepts the uploaded file and executes the script for processing.
Code flow
- Check for the existence of $action (should be set now)
- Begin displaying HTML for results of the upload
- Check to ensure that the file was uploaded
- Use
getimagesize()
to find out info about image uploaded - Report to the user the information gathered from the source file
- Display results to user
<?php if ($HTTP_POST_VARS['action']) { ?>
<HTML>
<HEAD>
<TITLE>File Upload Results</TITLE>
</HEAD>
<BODY BGCOLOR="WHITE" TEXT="BLACK">
<P><FONT FACE="Arial, Helvetica, sans-serif"><FONT SIZE="+1">File Upload
Results</FONT><BR><BR>
<?php
$uploadpath = '/path/to/store/uploaded/files/';
$source = $HTTP_POST_FILES['file1']['tmp_name'];
$dest = '';
if ( ($source != 'none') && ($source != '' )) {
$imagesize = getimagesize($source);
switch ( $imagesize[2] ) {
case 0:
echo '<BR> Image is unknown <BR>';
break;
case 1:
echo '<BR> Image is a GIF <BR>';
$dest = $uploadpath.uniqid('img').'.gif';
break;
case 2:
echo '<BR> Image is a JPG <BR>';
$dest = $uploadpath.uniqid('img').'.jpg';
break;
case 3:
echo '<BR> Image is a PNG <BR>';
$dest = $uploadpath.uniqid('img').'.png';
break;
}
if ( $dest != '' ) {
if ( move_uploaded_file( $source, $dest ) ) {
echo 'File successfully stored.<BR>';
} else {
echo 'File could not be stored.<BR>';
}
}
} else {
echo 'File not supplied, or file too big.<BR>';
}
?>
<BR><A HREF="<?php echo $PHP_SELF ?>">Back</A>
</FONT></P>
</BODY>
</HTML>
<?php } else { ?>
<!-- File Upload Form HTML Code Here -->
<?php } ?>
Final notes
Through the power of PHP, what used to be cumbersome and time-consuming tasks such as file submissions from your visitors can now be handled in any way you choose automatically! When a file comes in for processing, it can be moved into a database, e-mailed to a third party, or even opened up and processed through any of the functions available through PHP.
Special thanks to "ADMIN" for this week's Code Gallery Spotlight inspiration!
About John Coggeshall
John Coggeshall is a PHP consultant and author who started losing sleep over PHP around five years ago. Lately you'll find him losing sleep meeting deadlines for books or online columns on a wide range of PHP topics. You can find his work online at O'Reilly Networks onlamp.com and Zend Technologies, or at his website http://www.coggeshall.org/.
John has also contributed to WROX Press' Professional PHP4 Programming and is currently in the progress of writing the PHP Developer's Handbook published by Sams Publishing.