PHP File Upload R R




By: Richard (September 27, 2000)
File upload script in PHP.

This is a simple tutorial about putting together a file upload script through http forms.

Let's first try to understand what is happening when you do a file upload.

1. First you create a form that lets you browse for files on your local computer, and then click on the send button.

2. What happens after you click the send button? Well, what happens is that a script takes care of actually saving the file into a directory of your choice.

Let's look at these in turn.

Creating the html form.

I'm sure you're familiar with forms and how to create them. So we shouldn't have to go over that. Different form types are TEXT, TEXTAREA, HIDDEN, PASSWORD, FILE, SUBMIT, etc.

We will be concerned with FILE type here. Take a look at the following:

<form>
<input type="file">
<input type="submit" value="Upload">
</form>
What the above code will produce is this:

If you click on the button that says Browse..., you can select the file you would like to upload from your computer.

Currently, this form cannot do anything, since we haven't told it what to do with the file we choose to upload.

To do that, we will add an action attribute, like this:

<form action="scriptName">
<input type="file">
<input type="submit" value="Upload">
</form>
Now when we click on Upload button, the form knows to call scriptName for processing the upload. scriptName is the form handler.

In addition to the action attribute, we also have to tell the form the type of data we want to upload.

<form action="scriptName" ENCTYPE="multipart/form-data">
<input type="file">
<input type="submit" value="Upload">
</form>
Why do we need the multipart/form-data? Because it tells the form that the file we're about to transfer is in binary, rather than ascii format.

Finally, we need to indicate that we're using the post method. Whenever input type=file, post method should be used.

<form action="scriptName" ENCTYPE="multipart/form-data" method="post">
<input type="file">
<input type="submit" value="Upload">
</form>
Also, the input=file field must be given a NAME attribute. It is by this name that our form handler will know the file that was uploaded.

<form action="scriptName" ENCTYPE="multipart/form-data" method="post">
<input type="file" name="uploadedfile">
<input type="submit" value="Upload">
</form>
That takes care of our form. Next we need to create the script that will process the upload.

The form handler

Once the form has handed the file to the script, what happens next?

1. The script automatically writes the data to your OS's temporary directory.

2. The data cannot be used as it is in the temporary folder. It must be copied, moved, renamed, etc, to another location. The temporary folder only holds the data for a short while, before it gets deleted.

3. So the script must rename the file from the temp folder, and that completes the upload process.

Your temp folder is defined in php.ini. So if for some reason you need to change it, just open php.ini with your favorite text editor, and change the value of temp_dir.

Ok. As soon as the form hands over control to the form handler, the filename is stored in a variable. The variable is $uploadedfile. As you can see, $uploadedfile is whatever the name of the INPUT field of TYPE=file is in the upload form.

We can access various information about our file as follows:

$uploadedfile - The temporary filename in which the uploaded file was stored on the server machine.

$uploadedfile_name - This is the original name of the file on your computer. So for instance, if the file is called cityscape.jpg, you can find out from php by doing:

<?php
echo "$uploadedfile_name";
?>
PHP will print cityscape.jpg.

Other parameters are:

$uploadedfile_size - The size of the uploaded file in bytes.

$uploadedfile_type - The mime type of the file. An example would be "image/gif".

Note: before all of the above can work, register_globals must be turned on in php.ini. It's on by default.

File location

We have to define the folder in which we want php to place the file.

$upload_dir = "C:/data";
$saved_file = "$upload_dir/$uploadedfile_name";

Once again, let me repeat that when the file is first uploaded, it is held at in your OSs temporary directory. Your form handler now has to move the file from the temp directory to your defined final location, i.e. $upload_dir. The final location we want above is $saved_file. Assuming our file is name cityscape.jpg, we will have C:\data\cityscape.jpg.

Renaming the file

Now we can go ahead and rename the temporary file, to the new location we just defined:

rename( $uploadedfile, $saved_file );

All together

Let's put everything together now. The php form handler will contain the following:

<?php 
//you must have write access to this directory
$upload_dir = "C:/data";
$saved_file = "$upload_dir/$userfile_name";
rename( $uploadedfile, $saved_file );
?>
Put the above five lines in a file, and save it. You can call it uploader.php. It has to be a php file of course, since php will do the file processing.

Now the form code that we wrote before:

<form action="scriptName" ENCTYPE="multipart/form-data" method="post">
<input type="file" name="uploadedfile">
<input type="submit" value="Upload">
</form>

Now that we know the name of the form handler, let's change it under action attribute.

<form action="uploader.php" ENCTYPE="multipart/form-data" method="post">
<input type="file" name="uploadedfile">
<input type="submit" value="Upload">
</form>
Put the form code in a file and save it as uploader.html.

Now open it in your browser: http://localhost/uploader.html. You should be ready to go.

Using just one file, instead of two

At the moment, we have the form in one file, and the form handler in another. What if we want everything to be in one file? That is possible.

All we do is change the action attribute in the form to the same file. So if the single file we will have is upload.php, we will have action="upload.php". That way, when the form is submitted, the form will call itself.

First, we need to create two functions, one for the form, the other for the form handler. We're going to call the single file uploader.php.

function upload_form()
{
<form action="uploader.php" ENCTYPE="multipart/form-data" method="post">
<input type="file" name="uploadedfile">
<input type="submit" value="Upload">
</form>
}
function upload_file()
{
<?php 
//you must have write access to this directory
$upload_dir = "C:/data";
$saved_file = "$upload_dir/$userfile_name";
rename( $uploadedfile, $saved_file );
?>
}

To make this work, we must make the file smart. It must know when to put form handler, ie. the upload_file() function, into action. The first time file is loaded, there is no file chosen yet, and so we don't want upload_file() to act yet.

The script can check to see if a file has been submitted, by looking for a particular variable. Let's make that variable the NAME attribute in the form.

function upload_form()
{
<form action="uploader.php" ENCTYPE="multipart/form-data" method="post">
<input type="file" name="uploadedfile">
<input type="submit" value="Upload">
</form>
}
function upload_file()
{
<?php 
//you must have write access to this directory
$upload_dir = "C:/data";
$saved_file = "$upload_dir/$userfile_name";
rename( $uploadedfile, $saved_file );
?>
}
if(isset($uploadedfile))
{
upload_file();
}
else
{
upload_form();
}

Now that we have the IF statement, the form knows to either show the form, or process a file that has been passed to it.

ISSET is what is used in php to see if a variable is available. We could have also used something like IF($uploadedfile == "none"). It'd serve the same purpose.

Let's say for some reason we decide to rename our file from uploader.php to something else. Our form will seize working, unless the ACTION attribute is also changed. But php has a standard variable we can use, and that is $PHPSELF. This variable means "the current file". So no matter what the name of the file is, $phpself will make the file call itself.

To use $phpself, we need the file name only, not the path. So we use basename() function. Our final script will look like this:

function upload_form()
{
<form action="basename($phpself)" ENCTYPE="multipart/form-data" method="post">
<input type="file" name="uploadedfile">
<input type="submit" value="Upload">
</form>
}
function upload_file()
{
<?php 
//you must have write access to this directory
$upload_dir = "C:/data";
$saved_file = "$upload_dir/$userfile_name";
rename( $uploadedfile, $saved_file );
?>
}
if(isset($uploadedfile))
{
upload_file();
}
else
{
upload_form();
}

A script like this is what is known as a self-contained script.


Uploading multiple files

We now know how to upload a single file. What if we want to select multiple files and upload them at once?

Let's say we want to upload five files, we would create a form with five file fields as follows:







<form>
<input type=file>
<input type=file>
<input type=file>
<input type=file>
<input type=file>
<input type=submit value=send>
</form>
We need to add the action, encoding type, and method to the form tag:


<form action="scriptName" ENCTYPE="multipart/form-data" method="post">
<input type=file>
<input type=file>
<input type=file>
<input type=file>
<input type=file>
<input type=submit value=send>
</form>

<form action="scriptName" ENCTYPE="multipart/form-data" method="post">
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=submit value=send>
</form>
Did you notice that all the fields have exactly the same name, and also that the name contains []? Why are we using [] in the name?

In order to upload multiple files, the fields must be submitted to php as an array. We must also name each file field so that php will be able to recognize each field uniquely. Adding [] to the name tells php that all fields named multi[] is a member of the array.

Note: the name multi could be any word you choose, e.g. we could have named it myfiles[].

Since all the fields contain the same name multi[], how then would php differentiate between them? The answer to that is simple. Each file field is a member of an array and we can access each field using its index.

Another fact to know is that when a file is uploaded, it is saved in temporary folder with a temporary name. The temporary name can be accessed with $_FILES['uploadfile']['tmp_name'].

The actual name that a file is called when you uploaded it can be accessed with $_FILES['uploadfile']['name'].

Our aim then is to copy the file from the temporary folder to its actual name.

copy($_FILES['uploadfile']['tmp_name'],$_FILES['uploadfile']['name']);

Remember we said we can access each file using its array index? Therefore, we need to iterate through our submitted data and process each file upload individually. The code the follows should be self explanatory. for ($i=0;$i<5;$i++) { // we used 5 here because we have 5 file fields $tempName = $_FILES['uploadfile']['tmp_name'][$i]; $RealName = $_FILES['uploadfile']['name'][$i]; copy($tempName,$RealName); }

That's it. Just add as many file fields as you need to your form and you're set.

All together now:

Put this in the page that will show the form


<form action="scriptName" ENCTYPE="multipart/form-data" method="post">
<input type=file name="multi[]"
>
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=file name="multi[]">
<input type=submit value=send>
</form>
Put this in the php file that will process the form:
<?
for ($i=0;$i<5;$i++) { // we used 5 here because we have 5 file fields
$tempName = $_FILES['uploadfile']['tmp_name'][$i];
$RealName = $_FILES['uploadfile']['name'][$i];

copy($tempName,$RealName);
}
?>
It's up to you to include all necessary checks in the code to make sure people are only uploading what you want them to upload.

Home |  Comments, suggestions?





Copyright © 2000 Richie's Tutorials All rights reserved.