File Upload

It should be mentioned first, that the http 1.1 protocol comprises the upload function. The web browsers support an upload up to the level, that you can simply add a form input element

<input name="soubor" type="file">

and the upload will be generated including the "browse" button to select a file from your computer. The last thing you should to do in the form is to set the "enctype" parameter to level for the file sending:

<form action="upload.php" method="post" enctype="multipart/form-data">

By complete this, we can take the file.

Using Google, I have found two examples - but for original course, so both in the Czech:

Jaromír Skřivan on the Interval server

Tomáš Vinduška on the programujeme.com

Comparing them, we can see, how different could be the solution in php (different condition form - alternative syntax, generating everything in php, etc.).

Safety. There should be noticed, that if the file is not processed immediately or saved to the server (by our php script), it will be removed from the server after php script will end.
File upload could be safety risk, because user can save a php file to your directory (and execute it). Possible solution is to check extension, because on most servers only *.php files will be executed (the rest could be only be read from the computer). If you use the require or include function, check, if there is always the *.php extension used. The best solution is to insert the original file name into SQL table and generate a new name for the saved file. If anybody will like to have the original file, you can send it back by e-mail, create temporally copy or better, save only zipped files. You cannot disable the file execution using the Apache ".htaccess", because the php files will be executed, even if only the file reading will be permitted.
The best solution is in our second example - if we will only save a jpeg pictures, even using the resample function, our php program cannot be hacked using an upload.

The next text has been inspired from the example on the second link. On the both links there are used the same file for the upload form generating and for server upload itself. It is useful, if you like to send files one after another. This script should be included into some html page (somewhere inside the body tag). Note, that on the beginning of the file the "is_uploaded_file" function is called - for the first call, there are nothing to deal, so we should only generate the html form for the client side. Note, that the name of the php script should be "upload.php" (see black bold text):

<?php  
if (is_uploaded_file($_FILES["soubor"]["tmp_name"])):
                 // ^if the data sent to server are a file
  $cesta="data/"; //directory for saved files  
  if (move_uploaded_file ($_FILES["soubor"]["tmp_name"],
                   $cesta.$_FILES["soubor"]["name"])):
    //move file to our directory, //announce that it is sucessful
    echo "File ".$_FILES["soubor"]["name"];
    echo "with a size of ".$_FILES["soubor"]["size"];
    echo "bytes was sucessfully saved to server."; 
  else:  
    echo "Error saving file"; //error response  
  endif;  
else:
  echo "Error transphering file"; //another error response
endif;  
// generate the form for a new upload
?>
<form action="upload.php" method="post" enctype="multipart/form-data">
<input name="soubor" type="file">  
<br>  
<input name="Save" value="Save" type="submit"></form> 

Attention! Register globals!

In the red color is added using of associative (double-dimensional) array $_FILES - it should be used, if you cannot allow the "register global" parameter. If you like to delete it, then instead of $_FILES["soubor"]["name"] you should write $soubor_name (you need to include the underscore sign to denote the name, etc.).

This directive could be switched on, if you add section to your .htaccess file:

php_flag register_globals on
Order allow,deny
Allow from all

The php preprocessor was originally intended to translate small server side includes on the autors' (Rasmus Lerdorf ) personal home pages (from there this name). It was easy and simple to use. Now, the groups of -in real- professional programmers are trying to convert it to instrument for creating big portals and professional on-line webshops, even including object oriented programming. One of their modifications is to prohibit register globals at all. In this case, you need to use the $_FILES array. If you can use the register globals on, you can use scripts from the czech version of this page. This script has been fully tested. (the biggest difference is, that the $soubor_name variable you can simply write to text string (using double quotation), but cannot do this with text like $_FILES[soubor][name] ).

For the application of photo archive there is another problem - there is a size limit for a file, often as low as 2 MB. Many pictures with high resolution is today bigger.

Complete solution is in the next box (the name of the php script should be "upload1.php"):

<html>

 <head>
 <meta http-equiv="Content-Type"
 content="text/html; charset=windows-1250">
 <title>Odezva formuláře</title>

</head>

<body bgcolor="#FFFFFF">

<p><font size="4"><strong>File uploading</strong></font></p>

<?php  
if (is_uploaded_file($_FILES["soubor"]["tmp_name"])): //if the response contain a file
  $cesta="data/"; //our directory (where picture will be saved)  
    if (move_uploaded_file ($_FILES["soubor"]["tmp_name"], $cesta.$_FILES["soubor"]["name"])):
    //move file to our directory, //announce that it is sucessfull
     echo "File ".$_FILES["soubor"]["name"]." with the size of ";
     echo $_FILES["soubor"]["size"]." bytes was saved to server"; 

     $src = @imagecreatefromjpeg($cesta.$_FILES["soubor"]["name"]);   //open new file in the directory
           //there we should check, if it could be opened as a picture - please, add...
     $dst = imagecreatetruecolor(640,480);               //demanded resolution
           //new image with our preferred size is created
     imagecopyresampled($dst, $src, 0, 0, 0, 0, 640, 480, imagesx($src), imagesy($src));
           //parameters - see php.net/manual, imagesx/y are picture dimensions
     imagejpeg($dst, $cesta."1".$_FILES["soubor"]["name"],60);        //changing name by add the "1"
     imagedestroy($dst);           //destroying temporally files
     imagedestroy($src);
     //the saved file should be removed from the directory as well (please, add...)
  else:  
    echo "Error saving non-resampled file"; //Error message from the corresponding "if"
  endif; 
else:
  echo "Error transphering file"; //another error response
endif;  
//finally - generate form for sending another picture
//(in html, so end of php will follow:)
?>         

<hr>
<form action="upload1.php" method="post" enctype="multipart/form-data">
<input name="soubor" type="file">  
<br>  
<input value="Upload" type="submit"></form>  
<p>&nbsp;</p>
<sub>version from 25.3.2011</sub>
</body>
</html>

This script has been tested on the webzdarma.cz server, but has been modified for use on this page, so there could be errors.

Note: From w3schools:

By using the global PHP $_FILES array you can upload files from a client computer to the remote server.

The first parameter is the form's input name and the second index can be either "name", "type", "size", "tmp_name" or "error". Like this:

  • $_FILES["file"]["name"] - the name of the uploaded file
  • $_FILES["file"]["type"] - the type of the uploaded file
  • $_FILES["file"]["size"] - the size in bytes of the uploaded file
  • $_FILES["file"]["tmp_name"] - the name of the temporary copy of the file stored on the server
  • $_FILES["file"]["error"] - the error code resulting from the file upload

This is a very simple way of uploading files. For security reasons, you should add restrictions on what the user is allowed to upload.