Linux Setup Notes

name and address
created mar 16, 2009

How to upload a file using Apache and PHP

Summary

This article explains how to configure the Apache web server to upload files, with each file going to each user's home directory. It assumes you already have a webserver that supports php. See linuxsetup42.html for details on compiling Apache with PHP support.

Step 1: Edit httpd.conf or .htaccess

Add the following lines to the httpd.conf file:

LoadModule php5_module        modules/libphp5.so
AddHandler php5-script php 
DirectoryIndex index.html index.php  
AddType application/x-httpd-php .php .htm .html

The first three lines should already be present if php is working on your server. The last line adds support for inline php commands, which are needed to integrate environment variables such as usernames into your xhtml code. Re-start Apache so the new configuration takes effect.

If you don't have permission to change the httpd.conf file, the AddType command can also be added to a .htaccess file in your home directory. This may or may not work, depending on the setting of the AllowOverride line in httpd.conf.

Step 2: Make sure inline php is working

Add the line <?php echo "Inline php is working"; ?> /> into an html file.
Note: inline php will only work if the html file is in the designated html directory, where the server accesses it. If you load the same html file by typing "file:// ..." instead of "http:// ... " in the address bar, it won't work.

Here is a complete html file demonstrating inline php.

<html>
<head></head>
<body>
Test of inline php
<br />
<?php echo "This line will be visible if inline php is working
on this server.";?> 
</body>
</html>

When you click on the above page, you should see this:

inline php

Step 3: Create the upload form

Here is a complete upload form (upload.html). A real form would also have a more complete doctype header, including a line for the css page to control the formatting, but this example still works.

html file upload form
<html>
<head></head>
<body>
<h4> File uploads </h4>
<form enctype="multipart/form-data" action="../../cgi-bin/upload.php" 
	method="post">
<p>
Select File:
<input type="file" size="35" name="uploadedfile" />
<br />

Destination
<input type="text" size="35" name="destination" 
       value= "<?php echo $_ENV["USER"];?>" />
<br />
<input type="submit" name="Upload" value="Upload" />
</p>
</form>
</body>
</html>

Notes:

  1. This file requires a php file called upload.php (described below), which has to be placed in the cgi-bin directory.
  2. This form has a button for the user to select the source file, and a text area to specify the destination directory. Unfortunately, there is no easy way to select a directory using HTML. We could have added another input button, but it would always get a file, which would confuse the user. So we will get the directory from the user's text string and create a home directory for each user to put their files.
  3. The default directory is the user's username. This is obtained by reading the USER environment variable, using the following line of php: <?php echo $_ENV["USER"];?> . PHP defines a lot of other environment variables, including the server name, script name, date, etc. which can be accessed at any time within your html file. To get a list of these variables, put this line in your html file: <? phpinfo(); ?> .

Step 4: Create the php script

Here is a minimal but functional php script (upload.php) for uploading a file.

<?php

$destination_path = $_REQUEST["destination"] . "/"; 
$target_path = "../htdocs/" . $destination_path;
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']); 

echo "User=" .          $_ENV[USER] . "<br />";
echo "Source=" .        $_FILES['uploadedfile']['name'] . "<br />"; 
echo "Destination=" .   $destination_path . "<br />"; 
echo "Target path=" .   $target_path . "<br />"; 
echo "Size=" .          $_FILES['uploadedfile']['size'] . "<br />"; 
//echo "Tmp name=" .    $_FILES['uploadedfile']['tmp_name'] . "<br />"; 


if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['uploadedfile']['name']). 
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}
?>

Here is the output from the above script:

html file uploaded

Notes:

  1. This script would be placed in the cgi-bin directory, or wherever the server is configured to execute cgi scripts. The ExecCGI option must also be specified in the httpd.conf file in order for this script to work.
  2. The script strips the path from the user-specified file and appends the base filename to the directory that the user specified. In a real-world situation, you would have to be careful about this, because a user could type a variety of path characters to upload files in undesirable locations. For example, a user might be able to upload a new password file and obtain root access on your server.
  3. move_uploaded_file is a built-in PHP function.
  4. The upload.php script does not need to have execute permissions.
  5. The tjnelson directory (located in /usr/local/httpd/htdocs/ in this example) should be writable by the httpd process.
  6. It would be a good idea to hard-code the username in the script, instead of allowing them to change it. Otherwise, your users could overwrite each other's files.
  7. Making this script secure so your system doesn't get pwned five seconds after you post this form is, as usual, left as an exercise for the reader.

Back