PHP’s file upload configuration directives
PHP’s $_FILES superglobal array, used to handle file-upload data
PHP’s built-in file-upload functions: is_uploaded_file() and move_uploaded_file()
A review of possible error messages returned from an upload script
Several real-world examples are offered throughout this chapter, providing you with applicable insight into this topic.
Uploading Files via HTTP
Understand that this form offers only part of the desired result; whereas the file input type and other upload-related attributes standardize the way files are sent to the server via an HTML page, no capabilities are available for determining what happens once that file gets there. The reception and subsequent handling of the uploaded files are a function of an upload handler, created using some server process or capable server-side language such as Perl, Java, or PHP. The remainder of this chapter is devoted to this aspect of the upload process.
Uploading Files with PHP
Successfully managing file uploads via PHP is the result of cooperation between various configuration directives, the $_FILES superglobal, and a properly coded web form. In the following sections, all three topics are introduced, concluding with a number of examples.
PHP’s File Upload/Resource Directives
Several configuration directives are available for fine-tuning PHP’s file-upload capabilities. These directives determine whether PHP’s file-upload support is enabled, as well as the maximum allowable uploadable file size, the maximum allowable script memory allocation, and various other important resource benchmarks.
file_uploads = On | Off
Scope: PHP_INI_SYSTEM; Default value: On
The file_uploads directive determines whether PHP scripts on the server can accept file uploads.
max_input_time = integer
Scope: PHP_INI_ALL; Default value: -1
The max_input_time directive determines the maximum amount of time, in seconds, that a PHP script will spend attempting to parse input before registering a fatal error. The default value of -1 indicates unlimited time if the time is counted from the start of execution and not from the time input is available. This is relevant because particularly large files can take some time to upload, eclipsing the time limit set by this directive. Note that if you create an upload feature that handles large documents or high-resolution photos, you may need to increase the limit set by this directive accordingly.
max_file_uploads = integer
Scope: PHP_INI_SYSTEM; Default value: 20
The max_file_uploads directive sets an upper limit on the number of files that can be simultaneously uploaded.
memory_limit = integer
Scope: PHP_INI_ALL; Default value: 16M
The memory_limit directive sets a maximum allowable amount of memory in megabytes that a script can allocate, (Thevalue is provided in bytes but you can use shorthand by adding k, M, or G for kilo, Mega, and Giga bytes.) When you are uploading files, PHP will allocate memory to hold the content of the POST data in memory. The memory limit should be set to a vaue larger than post_max_size. Use this to prevents runaway scripts from monopolizing server memory and even crashing the server in certain situations.
post_max_size = integer
Scope: PHP_INI_PERDIR; Default value: 8M
The post_max_size places an upper limit on the size of data submitted via the POST method. Because files are uploaded using POST, you may need to adjust this setting upward along with upload_max_filesize when working with larger files. The post_max_size should be at least as big as upload_max_filesize.
upload_max_filesize = integer
Scope: PHP_INI_PERDIR; Default value: 2M
The upload_max_filesize directive determines the maximum size of an uploaded file. This limit is for a single file. If your upload multiple files with a single post request, this values sets the maximum size for each file. This directive should be smaller than post_max_size because it applies only to information passed via the file input type and not to all information passed via the POST instance. Like memory_limit.
upload_tmp_dir = string
Scope: PHP_INI_SYSTEM; Default value: NULL
Keep in mind that this directory must be writable by the user owning the server process. Therefore, if user nobody owns the Apache process, user nobody should be made either the owner of the temporary upload directory or a member of the group owning that directory. If this is not done, user nobody will be unable to write the file to the directory (unless world write permissions are assigned to the directory). If upload_tmp_dir is undefined or set to null the system defined tmp dir will be used. On most Linux systems this will be /tmp.
The $_FILES Array
The $_FILES superglobal stores a variety of information pertinent to a file uploaded to the server via a PHP script. In total, five items are available in this array, each of which is introduced here.
Note
Each of the array elements introduced in this section makes reference to userfile. This term is simply a placeholder for the name assigned to the file-upload form element and is not related to the file name on the user’s hard drive. You will probably change this name in accordance with your chosen name assignment.
$_FILES['userfile']['error']: This array value offers important information pertinent to the outcome of the upload attempt. In total, five return values are possible: one signifying a successful outcome and four others denoting specific errors that arise from the attempt. The name and meaning of each return value is introduced in the “Upload Error Messages” Section.
$_FILES['userfile']['name']: This variable specifies the original name of the file, including the extension, as declared on the client machine. Therefore, if you browse to a file named vacation.png and upload it via the form, this variable will be assigned the value vacation.png.
$_FILES['userfile']['size']: This variable specifies the size, in bytes, of the file uploaded from the client machine. For example, in the case of the vacation.png file, this variable could plausibly be assigned a value such as 5253, or roughly 5KB.
$_FILES['userfile']['tmp_name']: This variable specifies the temporary name assigned to the file once it has been uploaded to the server. This value is generated automatically by PHP when the file is saved to the temporary directory (specified by the PHP directive upload_tmp_dir).
$_FILES['userfile']['type']: This variable specifies the MIME type of the file uploaded from the client machine. Therefore, in the case of the vacation.png image file, this variable would be assigned the value image/png. If a PDF was uploaded, the value application/pdf would be assigned. Because this variable sometimes produces unexpected results, you should explicitly verify it yourself from within the script.
PHP’s File-Upload Functions
In addition to the number of file-handling functions made available via PHP’s file system library (see Chapter 10 for more information), PHP offers two functions specifically intended to aid in the file-upload process, is_uploaded_file() and move_uploaded_file() .
Determining Whether a File Was Uploaded
Moving an Uploaded File
Although copy() works equally well, move_uploaded_file() offers one additional feature: it will check to ensure that the file denoted by the filename input parameter was in fact uploaded via PHP’s HTTP POST upload mechanism. If the file has not been uploaded, the move will fail and a FALSE value will be returned. Because of this, you can forgo using is_uploaded_file() as a precursor condition to using move_uploaded_file() .
Of course, you can rename the file to anything you wish after it’s been moved. It’s important, however, that you properly reference the file’s temporary name within the first (source) parameter.
Upload Error Messages
UPLOAD_ERR_OK: A value of 0 is returned if the upload is successful.
UPLOAD_ERR_INI_SIZE: A value of 1 is returned if there is an attempt to upload a file whose size exceeds the value specified by the upload_max_filesize directive .
UPLOAD_ERR_FORM_SIZE: A value of 2 is returned if there is an attempt to upload a file whose size exceeds the value of the max_file_size directive , which can be embedded into the HTML form
Note
Because the max_file_size directive is embedded within the HTML form, it can easily be modified by an enterprising attacker. Therefore, always use PHP’s server-side settings (upload_max_filesize , post_max_filesize ) to ensure that such predetermined absolutes are not surpassed.
UPLOAD_ERR_PARTIAL: A value of 3 is returned if a file is not completely uploaded. This might happen if a network error causes a disruption of the upload process.
UPLOAD_ERR_NO_FILE: A value of 4 is returned if the user submits the form without specifying a file for upload.
UPLOAD_ERR_NO_TMP_DIR: A value of 6 is returned if the temporary directory does not exist.
UPLOAD_ERR_CANT_WRITE: A value of 7 is returned if the file can’t be written to the disk.
UPLOAD_ERR_EXTENSION: A value of 8 is returned if one of the installed PHP extensions caused the upload to stop.
A Simple Example
A Simple File-Upload Example
Caution
Remember that files are both uploaded and moved under the guise of the web server daemon owner. Failing to assign adequate permissions to both the temporary upload directory and the final directory destination for this user will result in failure to properly execute the file-upload procedure.
Although it’s quite easy to manually create your own file-upload mechanism, the HTTP_Upload PEAR package truly renders the task a trivial affair.
Summary
Transferring files via the Web eliminates a great many inconveniences otherwise posed by firewalls, FTP servers, and clients. There is no need for additional applications and security can be managed within the web application. It also enhances an application’s ability to easily manipulate and publish nontraditional files. In this chapter, you learned just how easy it is to add such capabilities to your PHP applications. In addition to offering a comprehensive overview of PHP’s file-upload features, several practical examples were discussed.
The next chapter introduces in great detail the highly useful Web development topic of tracking users via session handling.