Overview
This is simple tutorial that explains how to create an HTML form and use it to upload files with PHP. First, you will learn how to create the form. Then, you will learn how to receive the file via PHP and safely move it from the server's temporary directory into a more usable location.
Creating the Form
First, we're going to create an HTML form which will allow users to select a file. The form will consist of a file
input and a submit
button:
<form action="" method="post" enctype="multipart/form-data"> Select a file to upload<br /> <input type="file" name="user_file" /> <input type="submit" value="Upload" /> <input type="hidden" name="MAX_FILE_SIZE" value="2097152" /> </form>
The required pieces that make file uploads work are the enctype
attribute and the MAX_FILE_SIZE
hidden input element. The value of MAX_FILE_SIZE
is in bytes, so 2097152
bytes is equal to 2MB. For 5MB you would put 5242880
. (For an easy way to convert megabytes to bytes, check out the Google Calculator)
Note that the action
attribute is empty. This will cause the form to POST to itself. It is acceptable, though not necessary, to set this value to another page.
Now, we have a fully functional form that will upload a file to the server.
Receiving the Uploaded File
When a file is uploaded in this manner, it is automatically renamed and stored in the server's temporary directory. The names and locations will vary on different systems and server configurations, but the values are passed in the PHP $_FILES
array so you can easily access them.
Let's say our user uploads clowns.jpg
to our server. When the form posts and the upload completes, the $_FILES
array will look something like this:
Array ( [user_file] => Array ( [name] => clowns.jpg [type] => image/jpeg [tmp_name] => /var/tmp/phpB3AA.tmp [error] => 0 [size] => 10186 ) )
The name
element consists of the orignal filename, while the tmp_name
element is the actual location on the server. The mime-type is stored in type
, the file's size (in bytes) in size
, and the upload error code in error
(error code 0
means the upload was successful — refer to the PHP manual for a detailed explanation of PHP's file upload error codes).
At this point, PHP can read and write to the file from its temporary location, which is fine for some applications, but if you require that the file remain somewhere on the server or be accessible via the Web, you will need to move it to a safe location and rename it appropriately. To do this, it is best to use the move_uploaded_file()
function.
Let's move and rename the file from /var/tmp/phpB3AA.tmp
to /www/my_domain/files/clowns.jpg
:
<?php $from = $_FILES['user_file']['tmp_name']; $to = '/www/my_domain/files/' . $_FILES['user_file']['name']; if( move_uploaded_file($from, $to) ) { echo "Upload successful :)"; } else { echo "Upload failed :("; } ?>
Note that, if the same file exists in the new location, it will automatically be overwritten!
That's it, you're done! Just make sure you read the security warning below to ensure that you know how to protect your upload script(s) from being exploited.
Security Warning
Extreme caution should be taken when allowing the public (or any untrusted source) to upload files to your server. You should always check file extensions of uploaded files and disallow any potentially harmful filetypes (i.e. PHP, ASP, CF, etc.).
The reason? Server-side scripts that can be uploaded into a Web-accessible location can sometimes be executed by the uploader. A malicious person could use this exploit to gain access to scripts, data, usernames/passwords, or other sensitive information. It may even be possible for them to compromise your entire server.
It is recommended that, instead of disallowing a bunch of file extensions, you should allow only certain extensions that you specify. For example, if you are creating an image uploader that can upload JPEG, GIF, and PNG files, you should verify that the file uploaded has a JPG, JPEG, GIF, or PNG extension. (My check_extension() function may be useful in cases like this)
This is especially true if you don't maintain your own Web server. Imagine that you block out all of the scripting extensions that your Web host supports, and a month later they decide to add Ruby on Rails to their list of features without informing you (or, perhaps, you simply don't read the email they sent). Your upload script, and therefore your entire Web server, may become vulnerable if an attacker successfully uploads a malicious Ruby script.