|
|
|
|
|
|
| |
One of the more frequent questions seen on WeberDev is related to file uploading. In this tutorial I will explain how file uploading is done with PHP. Here are the steps :
1. Set up an html page with a form.
2. upload the file to the server.
3. Move the file to it's destination.
4. Let the user know if the upload was successful or not.
Setting up the upload form
Our main goal is to get a file from our local computer to the server. To do this, we need some kind of interface that will allow us to select the file and choose to submit it. Here is an example of such an interface: |
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
<TITLE>File Uploading Interface</TITLE>
</HEAD>
<BODY>
<FORM ENCTYPE="multipart/form-data" NAME=MyForm ACTION=submit.php METHOD="POST">
<TABLE>
<TR>
<TD>Choose File</TD>
<TD><INPUT NAME="MyFile" TYPE="File"></TD>
</TR>
<TR>
<TD COLSPAN="2"><INPUT NAME="submit" VALUE="Submit" TYPE="submit"></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
|
|
|
And this is how it looks : |
|
 |
|
Notice the ENCTYPE="multipart/form-data" part of the form. This is very important because without it the server will not know it is expecting a file upload.
Assuming we want to use one file to take care of the whole process we can add some PHP to take care of showing the FROM at the beginning and the results at the next stage.
Includes.inc is optional. Depending on how you include your functions and constants if you have any. You can simply remove it if you don't have such a file in use.
GetTextField() is used for security issues. It checks for the validity of the input of any variable you pass to it. This is not a built in PHP function. If you are not using such a function on your site you can remove it, however it is recommended. In this example we will use it for all input but you can use a different function for numeric input if you like. |
|
<?php
include"Includes.inc";
$command=GetTextField($_POST["command"]);
If($command == "") {
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<TITLE>File Uploading Interface</TITLE>
</HEAD>
<BODY>
<CENTER>
<BR><BR>
<FORM ENCTYPE="multipart/form-data" NAME=MyForm ACTION=submit.php METHOD="POST">
<INPUT TYPE="hidden" NAME="command" VALUE="1">
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="100000">
<TABLE>
<TR>
<TD>Choose File</TD>
<TD><INPUT NAME="MyFile" TYPE="File"></TD>
</TR>
<TR>
<TD COLSPAN="2"><INPUT NAME="submit" VALUE="Upload" TYPE="submit"></TD>
</TR>
</TABLE>
</FORM>
</CENTER>
</BODY>
</HTML>
<?php
}Else{
... upload script will go here after submission
}
?>
|
|
|
Setting up the upload script
Now that we took care of the front end, we need the backend on the server to take care of the incoming file and let us save it where we need it. This is where PHP comes in. PHP gives us the tools we need to save the file.
As of PHP Version 4.1.0 you should use the global $_FILES array. In it, you will find all of the needed information to accomplish the file upload. Here is one basic way to take care of the upload : |
|
<?php
$DestinationDir = "/home/berber/UploadedFiles/";
$DestinationFile = $DestinationDir . $_FILES['MyFile']['name'];
If (move_uploaded_file($_FILES['MyFile']['tmp_name'], $DestinationFile)) {
Echo "File uploaded successfully.";
}Else{
Echo $_FILES['MyFile']['error'];
}
?>
|
|
|
Notice that $_FILES['MyFile']['error']; will only work in PHP versions 4.2.0 and up.
At this stage we have all the code needed for a file upload. Lets look at the complete code : |
|
<?php
include"Includes.inc";
$command=GetTextField($_POST["command"]);
If($command == "") {
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<TITLE>File Uploading Interface</TITLE>
</HEAD>
<BODY>
<CENTER>
<BR><BR>
<FORM ENCTYPE="multipart/form-data" NAME=MyForm ACTION=submit.php METHOD="POST">
<INPUT TYPE="hidden" NAME="command" VALUE="1">
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="100000">
<TABLE>
<TR>
<TD>Choose File</TD>
<TD><INPUT NAME="MyFile" TYPE="File"></TD>
</TR>
<TR>
<TD COLSPAN="2"><INPUT NAME="submit" VALUE="Upload" TYPE="submit"></TD>
</TR>
</TABLE>
</FORM>
</CENTER>
</BODY>
</HTML>
<?php
}Else{
$DestinationDir = "/home/berber/UploadedFiles/";
$DestinationFile = $DestinationDir . $_FILES['MyFile']['name'];
If (move_uploaded_file($_FILES['MyFile']['tmp_name'], $DestinationFile)) {
Echo "File uploaded successfully.";
}Else{
Echo $_FILES['MyFile']['error'];
}
}
?>
|
|
|
When you press the submit button, the file goes from your computer to a temp directory on the server. The file is saved on the temp directory with a temp name so don't go looking for the file in the temp directory. Once the upload is complete, you use the move_uploaded_file() function to move the file from the temp directory to the destination you choose.
More info about the $_FILES Array from the Manual
- The array uses the name you gave the input field to access the data. in our example : "MyFile".
- $_FILES['MyFile']['name'] - The original name of the file on the client machine.
- $_FILES['MyFile']['type'] - The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted.
- $_FILES['MyFile']['size'] - The size, in bytes, of the uploaded file.
- $_FILES['MyFile']['tmp_name'] - The temporary filename of the file in which the uploaded file was stored on the server.
- $_FILES['MyFile']['error'] - The error code associated with this file upload. This element was added in PHP 4.2.0.
These are the error codes for $_FILES['MyFile']['error']
- UPLOAD_ERR_OK - Value: 0; There is no error, the file uploaded with success.
- UPLOAD_ERR_INI_SIZE - Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.
- UPLOAD_ERR_FORM_SIZE - Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
- UPLOAD_ERR_PARTIAL - Value: 3; The uploaded file was only partially uploaded.
- UPLOAD_ERR_NO_FILE - Value: 4; No file was uploaded.
- UPLOAD_ERR_NO_TMP_DIR - Value: 6; Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.
- UPLOAD_ERR_CANT_WRITE - Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0.
- UPLOAD_ERR_EXTENSION - Value: 8; File upload stopped by extension. Introduced in PHP 5.2.0.
Note: These became PHP constants in PHP 4.3.0.
Using $_FILES['MyFile']['error'] in our script
If we want to give the user a detailed explanation of why the upload failed we can make use of the $_FILES['MyFile']['error'] array in our script. Here is an example of how to do this. You can choose your own error description as you like. You can also choose to take action such as sending an email to the admin in case of Errors 6 or 7. |
|
<?php
}Else{
$DestinationDir = "/home/berber/UploadedFiles/";
$DestinationFile = $DestinationDir . $_FILES['MyFile']['name'];
If (move_uploaded_file($_FILES['MyFile']['tmp_name'], $DestinationFile)) {
Echo "File uploaded successfully.";
}Else{
switch($_FILES['MyFile']['error']) {
case 1 : Echo"The uploaded file exceeds the upload_max_filesize directive in php.ini.";
break;
case 2 : Echo"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.";
break;
case 3 : Echo"The uploaded file was only partially uploaded.";
break;
case 4 : Echo"No file was uploaded.";
break;
case 6 : Echo"Missing a temporary folder.";
break;
case 7 : Echo"Failed to write file to disk";
break;
case 8 : Echo"File upload stopped by extension";
break;
}
}
}
?>
|
|
|
Presetting files
One thing that can make a programmer loose sleep over is to try to preset a value in the VALUE="" attribute of the file field. Not many people know that this is not possible. While W3C says that this is possible, in practice, browsers like IE and FireFox do not allow a VALUE to be set. At first this sounds ridicules, why can't I preset a file with a path to make it easier on the user? Well, if you give it some though you realize that it's a huge security hole!!! Suppose you come to my site and I can preset a form with a file's name. What's to keep me from selecting to upload your /etc/passwd file? Moreover, I don't have to wait for you to press submit, I can simply set the filed and simulate a submit with JavaScript and ... Walla ... I can have access to any file on your computer. This is the reason that browsers simply ignore anything in the VALUE attribute of an <INPUT> tag of type file.
Limiting the file size
Another cool feature is the option to limit the size of the file being uploaded. All you need to do is add the next <INPUT> tag : |
|
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="100000">
|
|
|
In theory this will not allow the user to upload a file which is greater than 100KB. In practice, any info sent from the client can be manipulated so you can't trust this info. Also, many browsers ignore this field and the user will need to wait till the upload is over to find out that the file is too big. The only real limit on the file size is the upload_max_filesize directive in php.ini.
Permissions
Obviously you need to have permission to write to the destination directory. On Linux machines running apache the user that performs the upload is the anonymous user known as "nobody". This user must have write permissions to the destination directory or else you will get a message saying something like : |
|
Warning: Unable to create '/home/berber/berber.txt':
Permission denied in /home/berber/submit.php on line 5
|
|
|
Related Material
http://www.weberdev.com/file-uploads
http://www.weberdev.com/upload-max-filesize
http://www.weberdev.com/upload-tmp-dir |
|
| |
| 10 PHP Functions I Bet You Didn't Know About! Categories : PHP, PHP Functions, Filesystem, Arrays, Errors and Logging | | | File And Directory Manipulation In PHP (part 1) Categories : PHP, Directories, Filesystem | | | File And Directory Manipulation In PHP (part 2) Categories : PHP, Filesystem, Directories | | | Working With Text Files in PHP Categories : PHP, Filesystem | | | PHP 101 Part 5 of 15 : Rank And File Categories : PHP, Beginner Guides, Filesystem | | | An Alternative to Perl: Shell Scripting With PHP Categories : PHP, Shell Scripting | | | Managing a Simple Mailing List Categories : PHP, MySQL, Email | | | Create an LDAP Address Book with PHP Categories : PHP, LDAP | | | Apache, PHP, and PostgreSQL on RedHat Linux Categories : Apache, PHP, Databases, PostgreSQL, Linux | | | Aspect-Oriented Programming and PHP Categories : PHP, Aspect Oriented Programming | | | Uploading files to the server with PHP Categories : PHP, File System, HTML and PHP, HTTP | | | Building XML Trees with PEAR's XML_Tree Class Categories : PHP, Pear, XML | | | PHP And Regular Expressions 101 Categories : PHP, Regexps | | | How To add paging (Pagination) with PHP and MySQL Categories : PHP, Beginner Guides, Databases, MySQL, HTML and PHP | | | Simple ODBC Connections with PHP Categories : PHP, ODBC, Databases | |
| |
|
|