PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links | my php.net 
search for in the  
<CookiesFile-upload errors uitgelegd>
view the version of this page
Last updated: Tue, 22 Apr 2003

Hoofdstuk 18. Bestanden uploaden naar server

Met de POST methode uploaden

PHP kan 'file uploads' van elke RFC-1867 ondersteunende webbrowser (Dit zijn o.a. Netscape Navigator 3+ en Microsoft IE 3+). Dit maakt het mogelijk voor mensen om text en binary bestanden te uploaden. Met behulp van allerlei PHP-functies heb je volledige controle over wie er mag uploaden, en over het ge-uploade bestand zelf.

Gerelateerde Configuratie Aantekeningen: Zie ook file_uploads, upload_max_filesize, upload_tmp_dir, en de post_max_size directief in php.ini

PHP ondersteunt ook de PUT-methode voor bestand uploads. Dit wordt onder andere gebruikt door Netscape Composer en programma's die W3C's Amaya gebruiken. Zie PUT Methode Ondersteuning voor meer details.

Een 'bestands upload' scherm kan gemaakt worden met een speciaal form die er zo uit ziet:

Voorbeeld 18-1. Bestand Upload Form

<form enctype="multipart/form-data" action="_URL_" method="post">
 <input type="hidden" name="MAX_FILE_SIZE" value="1000">
 Upload dit bestand: <input name="userfile" type="file">
 <input type="submit" value="Upload!">
 </form>
De _URL_ moet naar een PHP bestand wijzen. Het MAX_FILE_SIZE 'hidden' veld moet VOOR het 'file input' veld komen en de waarde hiervan wordt gebruikt als de maximaal toegestane grootte van het bestand dat geupload wordt. Deze waarde is in bytes.

Waarschuwing

De MAX_FILE_SIZE is een 'advies' aan de browser. Het is niet moeilijk om deze te omzeilen!! Reken er dus niet op dat het werkt... De PHP-setting voor maximum-size is daarentegen niet te omzeilen.

De variabelen voor geuploade bestanden kunnen verschillen, dit kan liggen aan de PHP-versie en de configuratie: De autoglobal $_FILES bestaat sinds PHP 4.1.0, terwijl de $HTTP_POST_FILES array al bestaat sinds PHP 4.0.0. Deze arrays bevatten alle informatie over het geuploade bestand. Het gebruik van $_FILES wordt aangeraden. Als register_globals aan staat, zullen gerelaeerde variabelen ook bestaan. register_globals staat standaard uit sinds PHP .

De inhoud van de $_FILES array van het voorgaande voorbeeld is als volgt: (dit gaat uit van userfile, zoals gebruikt in het voorgaande voorbeeld)

$_FILES['userfile']['name']

De (gegeven) naam van de geuploade file.

$_FILES['userfile']['type']

De mime-type van het bestand, zoals gegeven door de browser. (Het kan voorkomen dat geen mime-type wordt gegeven, of een verkeerde wordt gegeven) The mime type of the file, if the browser provided this Een voorbeeld hiervan zou kunnen zijn "image/gif".

$_FILES['userfile']['size']

De bestandsgrootte in bytes.

$_FILES['userfile']['tmp_name']

De tijdelijke naam van het bestand, dit is ook de plaats waar het bestand tijdelijk is opgeslagen totdat het script er iets mee doet. Dit bestand wordt weggehaald zodra het script eidigt.

$_FILES['userfile']['error']

De error code ge-associeerd met deze bestands-upload. ['error'] bestaat pas sinds PHP 4.2.0

Opmerking: In PHP versies voor 4.1.0 heette deze array nog $HTTP_POST_FILES, ook was het geen autoglobal zoals $_FILES is. PHP 3 maakt geen gebruik van $HTTP_POST_FILES, noch van $_FILES.

Als register_globals aan staat in php.ini, zijn er extra variabelen beschikbaar. Bij voorbeeld, $userfile_name zal dan gelijk zijn aan $_FILES['userfile']['name'], $userfile_type zal gelijk zijn aan $_FILES['userfile']['type'], etc. Sinds PHP 4.2.0 staat register_globals standaard uit. Het is dus niet aan te raden om te vertrouwen op het bestaan van deze variabelen.

Ge-uploade bestanden worden standaard in de standaard tijdelijke directory van de server opgeslagen, tenzij er een andere locatie is opgegeven met het upload_tmp_dir directive in php.ini. De standaard tijdelijke directory kan worden veranderd worden door de 'environment' variable (TMPDIR) te veranderen in het 'environment' waar PHP in draait. Dit kan niet in een script mbv de putenv() functie gedaan worden. Deze 'environment' variable kan ook gebruikt worden om zeker te weten dat bepaalde andere bewerkingen op alle ge-uploade bestanden werken.

Voorbeeld 18-2. Validating file uploads

De volgende voorbeelden werken alleen met PHP versies 4.0.2 en hoger. Zie ook: is_uploaded_file() en move_uploaded_file().

<?php 
    // Voor PHP 4.1.0 moet $HTTP_POST_FILES gebruikt worden in plaats van $_FILES.
    if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
        copy($_FILES['userfile']['tmp_name'], "/plaats/om/heen/te/verplaatsen");
    } else {
        echo "Mogelijke aanval gespot: " . $_FILES['userfile']['name'];
    }
    /* ...of... */
    move_uploaded_file($_FILES['userfile']['tmp_name'], "/plaats/om/heen/te/verplaatsen");
    ?>

Het script dat het bestand ontvangt moet zo veel mogelijk zijn best doen om het bestand goed te plaatsen. Je kan bijvoorbeeld $_FILES['userfile']['size'] gebruiken om te grote of te kleine bestanden te verwerpen. Je kan $_FILES['userfile']['type'] gebruiken om bepaalde typen bestanden niet door te laten. Sinds PHP 4.2.0, kan je ook $_FILES['userfile']['error'] gebruiken met behulp van error codes. Het maakt niet uit wat je verzint, om het bestand te behouden, moet het �f hernoemd zijn, of verplaatst

Als geen van beiden heeft plaatsgevonden, zal het bestand aan het einde van het proces, intern verwijderd worden.



User Contributed Notes
Bestanden uploaden naar server
add a note add a note
jeffp-php at outofservice dot com
05-Jan-2001 03:36

$HTTP_RAW_POST_DATA --

You'll usually access variables from forms sent via POST method by just accessing the associated PHP global variable.

However, if your POST data is not URI encoded (i.e., custom application that's not form-based) PHP won't parse the data into nice variables for you.  You will need to use $HTTP_RAW_POST_DATA to access the raw data directly. (This should return a copy of the data given to the PHP process on STDIN; note that you wan't be able to open STDIN and read it yourself because PHP already did so itself.)

16-Jan-2002 08:09
This example is was a bit confusing for me... didn't get a file to upload till I looked here.

Louis at ewens dot com
30-Jan-2002 02:33

Some restrictive firewalls may not let file uploads happen via a form with enctype="multipart/form-data".

We were having problems with an upload script hanging (not returning content) when a file was uploaded through a remote office firewall. Removing the enctype parameter of the form allowed the form submit to happen but then broke the file upload capability. Everything but the file came through. Using a dial-in or other Internet connection (bypassing the bad firewall) allowed everything to function correctly.

So if your upload script does not respond when uploading a file, it may be a firewall issue.

m dot ullmann at digital-family dot de
02-Feb-2002 01:02

There is one thing open.

I am using PHP 4.1.1 on Apache / Linux. The upload procedure _requires_ that you have a line that sets the maximum file size in your form:

<input type="hidden" name="MAX_FILE_SIZE" value="100000">

(value in bytes)

yogi at darkmag dot net
15-Feb-2002 03:52

There's a strange issue with file uploading and mime types, it seems it depends of the browser..

With a file upload system, the above code will show differents results :

echo "type : ".$HTTP_POST_FILES["image"]["type"]." name : ".$HTTP_POST_FILES["image_thb"]["name"]." tmpname : ".$HTTP_POST_FILES["image"]["tmp_name"]." size : ".$HTTP_POST_FILES["image"]["size"] ;

where 'image' is an input (type='file') field.

On IE, it gives :
type : image/pjpeg name : apercuclip.jpg tmpname : /tmp/phpwYQzWO size : 5182

Ok, normal, let's try another

On Netscape6 it gives :
type : image/jpeg name : apercuclip.jpg tmpname : /tmp/php6jgmQR size : 5182

note that the mime type is now image/jpeg and not image/pjpeg

On Opera6 :
type : image/jpeg; name=\"apercuclip.jpg\" name : apercuclip.jpg tmpname : /tmp/php655KLf size : 5182

Still image/jpeg, but there's also a "name" value ! weird result..

So be careful with that while uploading file..

wodokm at in dot tum dot de
18-Feb-2002 06:55

The

enctype="multipart/form-data"

part in the <form ...> field is very important, if you forget it you won't get the $userfile, $userfile_name, $userfile_size, $userfile_type veriables set (correctly). So if you're adding a File Input Field in a form, don't forget to add the above part (I did it and wondered why the vars were not set correctly).

jim dot dam at sympatico dot ca
27-Feb-2002 03:13

Some browsers label the type differently.  I found this out while trying to restrict the file types that could be uploaded.  I created a simple script that will let the user upload a file, and then print_r() the $_FILES variables.  In Microsoft Internet Explorer 6.0.26 on Windows XP, I got this result:

Array
(
   [file] => Array
       (
         [name] => command.com
           [type] => application/octet-stream
           [tmp_name] => C:\WINDOWS\TEMP\phpBE.tmp
           [size] => 50620
      )

)

Uploading the same file with the same script in Opera 6.01 (again on Windows XP), I got this result:

Array
(
  [file] => Array
       (
           [name] => command.com
           [type] => application/octet-stream; name="command.com"
           [tmp_name] => C:\WINDOWS\TEMP\phpBF.tmp
           [size] => 50620
      )

)

The tmp_name is obviously supposed to be different, but notice how the name of the file was appened to type.  My solution is either (a) split() at the semicolon and use the first element of that array, or (b), search the type for the allowed filetypes (via strstr()).

michaelpearl at mac dot com
04-Mar-2002 09:05

When uploading very large files (greater than the default 8M) I found that I had alter not only the "max_file_size" input and the php.ini max_file_size limit, but ALSO the "post_max_size" variable in the php.ini file.

Because I was submitting the file via a POST request, it would hit this limit and deny the upload.

am at netactor dot NO_SPAN dot com
15-Mar-2002 05:20

Your binary files may be uploaded incorrectly if you use modules what recode characters. For example, for Russian Apache, you should use
<Files ScriptThatReceivesUploads.php>
CharsetDisable On
</Files>

mail at philipp-louis dot de
24-Mar-2002 09:14

If no file was uploaded, you would probably expect the $userfile variable (or whatever its name is) to be empty. But it isn't. It contains the string "none" instead.

I don't know if this is true for all systems and configurations, but the fact that it *might* be the case is reason enough *not* to use things like that in order to check whether a file was uploaded:

// This is bad:
if($userfile == "")
 echo "You did not upload any file!";

Instead, you might want to check $userfile_size. But note that this method makes no difference between NO and an EMPTY file:

// This is better:
if(!$userfile_size)
 echo "Either you did not upload any file, or you uploaded an empty file!";

jeroenHATESSPAM at NOSPAMvogelpoel dot com
16-Apr-2002 11:50

Don't forget to allow file uploads by other users for the directory you use as file-upload destination. Same thing for the temporary-file directory.

Just CHMOD the directories to 777 and it should work, granted the PHP code itself is working okay.

seanogoconaire at yahoo dot com
24-Apr-2002 12:27

in reply to:
[email protected]
19-Apr-2002 07:46

open_dir restriction is when the folders on your server are read only for the current user (public).

 You must edit the properties of that folder in some FTP program.  Setting the properties to 777 should remove this problem.
Also typing
error_reporting(7);
in your code will hide the error from the users.

meto at compatibility dot info
25-Apr-2002 01:01

Just another way to handle multiple uploads:

<?
function upload($FVARS) {
  for($i=0;$i<count($FVARS[file][tmp_name]);$i++) {
     $size=$FVARS[file][size][$i];     // filesize
    $type=$FVARS[file][type][$i];     // mime type
    $name=$FVARS[file][name][$i];     // original name
    $temp=$FVARS[file][tmp_name][$i]; // temporary name
     if($size) {
        //whatever to do with uploaded files
        echo "original name: $name<br />";
        echo "temporary name: $temp<br />";
        echo "mime type: $type<br />";
        echo "size: $size<hr />";
     }
  }
}

upload($HTTP_POST_FILES); // or $_FILES or whatever
?>

Using this function every <input type="file" name="file[]"> will be handled.

mjm at porter dot appstate dot edu
02-May-2002 11:53

To check to see if a file was actually uploaded, it is safer to check the value of ($_FILES["name"]["size"] > 0) than to check (!empty($_FILES["name"]["tmp_name"])) beacuse some versions of PHP will store 'none' in $_FILES["name"]["tmp_name"] while others will leave it empty in the case od a missing file.
solja at gci dot net
04-May-2002 01:11

Just another way I found to keep an uploaded file from overwriting an already exisiting one - I prefix each uploaded file with time() timestamp. Something like:
$unique_id = time();

Then when I give the new name to move the file to, I use something like:
$unique_id."-".$filename

So I get a fairly unique filename each time a file is uploaded. Obviously, if two files are uploaded at once, both will have the same timestamp, but I don't worry too much about that. Hope this might help someone.

edg at NOSPAM dot greenberg dot org
07-Jun-2002 08:39

It should be noted that there is a control for file uploads in PHP.INI which must be on for any of this to work. In fact, my experience is that if file uplods are turned off in php.ini, NONE of the fields in a multipart/form-data form will be passed to PHP. This will be truw whether or not a file is being uploaded.
seven_overseas at hotmail dot com
08-Jun-2002 01:25

I was having problems with the returned upload array. The name, and type were returned, but tmp_name was empty and size was set as 0.

I removed the maxfilesize input type, and it worked perfectly again, all of the elements of the array were present. Odd but true. Hope this helps someone out.

jasonyeast at hotmail dot com
14-Jun-2002 06:29

Dave has a good upload class working with 4.2.1
trey at fishleg dot com
24-Jun-2002 08:24

I've pieced this together out of bits I've found elsewhere, but the info belongs here.

If you're on a shared host that won't allow you to modify the php.ini file and your max_upload_size is set low, you can create an .htaccess file in the upload handler script directory that contains:

php_value upload_max_filesize 8000000

(example set for 8 megs)

As a nice side benefit, it will keep big uploads from being erroneously listed as an upload attack via many of the scripts found here ;)

j-php at pureftpd dot org
29-Jun-2002 06:54

Always use move_uploaded_file() to have your uploaded file in a suitable location, not copy() .

move_uploaded_file() is easier and more secure.

And it will work in safe_mode and with an open_basedir.

It your customers complain about errors like :

Warning: open_basedir restriction in effect. File is in wrong directory in
/users/sexydoo/www.bitchy-sex.com/html/inscription.php on line 40

with scripts managing uploaded files, tell them to replace copy() calls with move_uploaded_file() .

max_bld at tin dot it
14-Jul-2002 06:53

Well, it could look so obvious, but I spent some hour asking to myself why the hell the whole thing didn't work: when I sent POST with ENCTYPE="multipart/form-data", I did find the file uploaded into /tmp, but the post data were completely BLANK!! The matter was that the php.ini file actually has a file_uploads directive, and in my Red Hat 7.3 distro it is Off by default.
rynop2000 at hotmail dot com
19-Jul-2002 05:57

--HANDLING LARGE FILE UPLOADS and entering into a MySQL blob field--

Hope this helps someone as it was a bitch to fig out. MySQL default buffer and packets are set small.  here is a method to get aroudn it.

$filehandle = fopen($addfile, "r");
$filesize = filesize($addfile);

//now this is bullshit, but have to read the file piece by piece and insert because the mysql server is set up to only handle 1meg inserts (small buffer and packet).

$buffer = addslashes(fread($filehandle, 906240));
$query = "Insert into files (file, filename, size, userid ) values ('$filedata','$addfile_name', '$filesize')";
$this->query($query);
$id = mysql_insert_id($this->link_id());

while (!feof ($filehandle)) {
 $buffer = addslashes(fread($filehandle, 906240));
 $query = "UPDATE files SET file = concat('$buffer') where id='$id'";
 $this->query($query);
}
fclose ($filehandle);

alexis at mvs dot com
26-Jul-2002 06:27

[[editors note: mention in docs to check size > 0]]

If you have a script like this:

<?
if ($_REQUEST["answered"] == "ok") {
 echo "<pre>";
   echo $_SERVER["SERVER_SOFTWARE"] . "\n\n";
   if (is_uploaded_file($_FILES["userfile"]["tmp_name"]))
       echo "It really is an Uploaded File!\n";
  else
       echo "It is NOT\n";
   echo "These are the contents of the \$_FILES array :: \n";
  print_r($_FILES);
 echo "</pre>";
 
} else {
?>

<form name="forma" action="file_problem.php" method="post" ENCTYPE="multipart/form-data">
 <input type="file" name="userfile">
 <input type="hidden" name="answered" value="ok">
 <input type="submit">
</form>

<?}?>

**** This is the result when we run it in PHP 4.1.2 browsing a real file from our disk:

Apache/1.3.24 (Unix) PHP/4.1.2

It really is an Uploaded File!
These are the contents of the $_FILES array ::
Array
(
   [userfile] => Array
       (
          [name] => wtrs.audit
           [type] => text/plain
         [tmp_name] => /var/tmp/phpTMaO4e
           [size] => 30313
       )

)

**** And this is the result in PHP 4.2.2 :

Apache/1.3.26 (Unix) PHP/4.2.2

It really is an Uploaded File!
These are the contents of the $_FILES array ::
Array
(
   [userfile] => Array
       (
          [name] => wtrs.audit
           [type] => text/plain
         [tmp_name] => /var/tmp/phpU6a4fK
           [error] => 0
           [size] => 30313
      )

)

Everything seems to work fine, In fact in 4.2.2 we have a nice variable "error" in the array to be sure that there was no error during the upload.

BUT!

If we select a 0 byte file from our disk or if we simply write a bogus name in the userfile field before submiting the form we have these VERY different results:

**** In PHP 4.1.2:

Apache/1.3.24 (Unix) PHP/4.1.2

It is NOT
These are the contents of the $_FILES array ::
Array
(
   [userfile] => Array
      (
           [name] => sdfsdf
           [type] => application/octet-stream
           [tmp_name] => none
         [size] => 0
       )

)

... very nice, we can use the "none" in the tmp_name to determine that this is not a correct file and that we don't have to move it to our directory maybe damaging an already stored file with that name.

*** In PHP 4.2.2 :

Apache/1.3.26 (Unix) PHP/4.2.2

It really is an Uploaded File!
These are the contents of the $_FILES array ::
Array
(
   [userfile] => Array
       (
          [name] => sdfsdf
           [type] => application/octet-stream
           [tmp_name] => /var/tmp/phpNaaagK
           [error] => 0
           [size] => 0
       )

)

... this is bad because PHP assumes a file was uploaded and creates a tmp_file in the server, also it doesn't report an error in the "error" variable of the array, and of course is_uploaded_file returns true.  

Now we have no way to determine if the uploaded file was really a file and we will finish coding something like "IF FILESIZE IS 0 THEN DISCARD THE UPLOAD", but then we won't be able to upload 0 byte files (as we could in earlier version of PHP).

Is this a bug?  any ideas of working this arround?  

Constructions like these won't work any more:

if (!empty($userfile_name) && is_uploaded_file($userfile))
       move_uploaded_file($userfile, "$ruta2".$userfile_name);

...assuming that register_globals is on;  or:

$userfile = $_FILE["userfile"]["tmp_name"];
$userfile_name = $_FILE["userfile"]["name"];
if ( $userfile != 'none' && is_uploaded_file($userfile))
      move_uploaded_file($userfile, "$ruta2".$userfile_name);

... if register_globals are off.

someone at example dot com
30-Jul-2002 12:11

In my opinion PHP 4.2.2 behaves correctly. It may be not as nice as before, but cleaner. If the user sends an empty file you get an empty file. If the user types a bogus file name it is the responsibility of the browser to tell the user that the file cannot be found.
I would not consider the PHP 4.2.2 behaviour a bug, but the change in behaviour could be considered a bug.

bradley at bestweb dot net
04-Sep-2002 09:44

Make sure that you set METHOD="POST" on the form you are using to submit the file.
If you don't, $userfile will simply be the directory on your local machine, and none of the other php variables will work ($userfile_name, $userfile_type, or any of the $_FILES vars)

martellare at hotmail dot com
19-Sep-2002 05:13

[EDITOR'S NOTE]
It is unsafe to trust a browser in such cases. Instead of using:
<input type="hidden" name="MAX_FILE_SIZE" value="1">

You should use (after upload):
if($_FILES['userfile']['size'] <= 1){
// do stuff
}else{
echo 'file too big';
}
[/NOTE]

Just to note... I've found that it is very import where you place your <INPUT type="hidden" name="MAX_FILE_SIZE"> tag in your <FORM>.  It must be before your <INPUT type="file">, or else it won't be accepted.  I found that this would affect code [email protected]'s (above).  The following form...

<form ENCTYPE="multipart/form-data" method="POST">
<input TYPE="FILE" NAME="userfile">
<input type="hidden" name="MAX_FILE_SIZE" value="1">
<input type="submit">
</form>

... Will accept ANY file up to the the MAX_FILE_SIZE directive in php.ini.  If you move things around like this

<form ENCTYPE="multipart/form-data" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1">
<input TYPE="FILE" NAME="userfile">
<input type="submit">
</form>

...it will then restrict files to <= 1 byte.

(I experienced this issue on IE 6.0 and Netscape 4.08, PHP 4.2.2, running Win XP)

j.h.westerATplanetDOTnlHATESSPAM
03-Oct-2002 06:57

See also my note above.
In my example the two files with no tmp_name and zero size were bigger then the max_file_size. They are not uploaded, but excist in the $_FILES / $HTTP_POST_FILES.

I changed the script a bit so you get a error when a file is to big or is empty:

<?
function upload($FVARS) {
for($i=0;$i<count($FVARS[file][tmp_name]);$i++) {
$size=$FVARS[file][size][$i]; // filesize
$type=$FVARS[file][type][$i]; // mime type
$name=$FVARS[file][name][$i]; // original name
$temp=$FVARS[file][tmp_name][$i]; // temporary name
//whatever to do with uploaded files
echo "original name: $name<br />";
if($size > 0) {
echo "temporary name: $temp<br />";
echo "mime type: $type<br />";
echo "size: $size<hr />";
}
else {
echo "file is empty or exceeded the upload size";
}
}
}

upload($HTTP_POST_FILES); // or $_FILES or whatever
?>

to use in your form:
<input type="file" name="file[]">

support at oeko dot net
10-Oct-2002 09:35

safe_mode *can* be used together with file upload.
One needs to set appropriate values for the upload
variables on a per-user basis, though. Added benefit: Users can't mangle other user's files easily.

themaster at themasterofpixels dot com
17-Oct-2002 10:01

One of the problems with uploading files may not even be in your php code. Make sure the value of the MAX_FILE_SIZE field in the upload form is set to be not smaller then the size of the file to upload
kurmie at wanadoo dot nl
17-Oct-2002 02:59

Uploading huge files still remains a problem, even after you've set upload_max_size and post_max_size to reasonable sizes (in my case respectively the defaults 2M and 8M).

MAX_FILE_SIZE is often ignored and php doesn't cut in to stop the transfer, so if you're using Apache (i'll bet you are) try limiting transfers with LimitRequestBody.

Be advised that you don't set this directive too low, or Apache will return a document without data.

bckman at ix dot netcom dot com
15-Nov-2002 01:01

Remember that it is possible for a user to upload a php file. If the user can then figure out your directory structure, (which they almost certainly can!) they can then run the script and cause all kinds of mischief!

Use $_FILES['userfile']['name'] to check for the file suffix of the uploaded file, and if it happens to be 'php' either change the suffix or refuse to place it on your server

Frank Boumphrey

jflaflamme at votremedia dot com
21-Nov-2002 06:46

Just to prevent some people to **** one hour on that ...

enctype="multipart/form-data"

MUST BE IN THE FORM TAG !!!

I got php 4.1.2

g dot kakanauskas at paciolis dot lt
30-Nov-2002 06:40

If you are planning to upload large files and use the script used in the description, do not forget to set max_execution_time in php.ini to a reasonable value, because it seems like the script is running until the upload is over and you will get

Fatal error: Maximum execution time of xx seconds exceeded.

The error occurs only AFTER the file is uploaded and I believe it's because php wait's for $_FILES variables to appear too long...

dulink at scriptmatrix dot com
03-Dec-2002 06:14

After spending several useless hours trying to figure out why I couldn't upload files on an NT server, I stumbled opon the answer..

For it to work on a windows box, you must use the full path.
Example:
copy($_FILES['userfile']['tmp_name'], "c:\\path\\to\\upload_dir\\" . $_FILES['userfile']['name']);

not:
copy($_FILES['userfile']['tmp_name'], "/path/to/upload_dir/" . $_FILES['userfile']['name']);

Also notice the double \\s. As far as I can tell, you must do it this way or it will not work on a windows based server.

I hope this helps save some time for ppl working with winblows.

alex at sara-and-david dot com
04-Dec-2002 12:25

Here's a quick, simple, and easily modified way to determine file type of the uploaded file. (I used images for my example.)

$imgarray = array("image/pjpeg", "image/jpeg", "image/gif", "image/png", "image/x-png");

$filetype = $_FILES['userfile']['type'];
$filename = $_FILES['userfile']['name'];
$filesize = $_FILES['userfile']['size'];

if (!$filesize){
echo "The file you specified is either an invalid name, or contains Zero bytes.";
}elseif (!in_array($filetype,$imgarray)){
echo 'Invalid filetype. Please use only a .JPG, .GIF, or .PNG file.';
}else{
echo 'You\'ve uploaded a file named '.$filename.'!';
}

pieroc at tin dot it
04-Dec-2002 07:23

when i use multipart/form-data in data upload, if the file contains low value (00 exadecimal) the data transferring always stops at low value char.
travis dot lewis at amd dot com
04-Dec-2002 07:58

If you we dumb like me you installed Redhat 8.0 and kept the default install of packages for Apache 2.0 and PHP4.2.2.  I could not upload any files larger than 512kB and all the php directorives were set to 32MB or higher.
memory_limit = 128M
post_max_size = 64M
upload_max_filesize = 32M

And my upload web page was set to 32MB as well:
<Form ID="frmAttach" Name="frmAttach" enctype="multipart/form-data" action="attachments.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="33554432" />

However, the insiduous php.conf (/etc/httpd/conf.d/php.conf) file used by default RPM install of Redhat httpd has a LimitRequestBody set to 512kB ("524288" ).  Adjusting this to 32MB ("33554432") got things going for the larger files.  Here is my php.conf file in its entirety.  Hope this helps someone. L8er.

#
# PHP is an HTML-embedded scripting language which attempts to make it
# easy for developers to write dynamically generated webpages.
#

LoadModule php4_module modules/libphp4.so

#
# Cause the PHP interpreter handle files with a .php extension.
#
<Files *.php>
   SetOutputFilter PHP
   SetInputFilter PHP
   LimitRequestBody 33554432
</Files>

#
# Add index.php to the list of files that will be served as directory
# indexes.
#

briantmeyer at earthlink dot com
11-Dec-2002 08:17

Not really an issue specific to upload scripts, but having to do with timeouts that seem to happen for no reason after 3 minutes. But since uploads take so long, this is where people will run into them. This is an IIS specific fix after you have done what you need to do to php.ini as well as your script.

I ran into this trying to upload 20 meg files. It would timeout after 3 minutes or so no matter what. I checked everything in iis, php.ini, and in the script. Finally a person by the name of michael defrees showed me what was wrong. It is an IIS issue, there is a timeout in a weird place in addition to the normal "connection timeout" setting under the 'web site' tab.

To fix go to 'www root properties'
then 'home directory' tab
click on 'configuration' (bottom right)
This gives you the 'app mappings'
click on the 'Process Options' tab
then you'll see the setting for CGI script timeout for what you want.

panayotis at yellownetroad dot com
18-Dec-2002 10:21

In order to enable $HTTP_RAW_POST_DATA, you can set always_populate_raw_post_data to On either in php.ini or .htaccess
acsguy at wtp dot net
31-Dec-2002 09:42

Just a quick note on permissions for upload directory:

You need execute rights (chmod 777) in oder for move_uploaded_file() to work.

B-)

mccorkle+php at devteam dot org
08-Jan-2003 06:59

To anyone that is trying to use values="foo" to set a default value in a input type of ``file'', I found this out from

* Internet Explorer, Netscape and Opera do not use the VALUE attribute as the default contents of the input area. Any default value set via HTML is not usable via scripting and the DOM as well (hence it is not listed as 'supported' in any of the browsers.) If a user enters text in the field however, that value is then reachable via the DOM as it normally would be for a normal INPUT field (via the .value property.) The reason for this behavior would presumably be to ensure the security/safety of users against malicious authors.

Tooke me a bit to find this, so I figured I'd share.

Travis Perreira [travis at justravis dot com]
09-Jan-2003 12:18

Is your script returning "Warning: Unable to open 'userfile' for reading: No such file or directory.?"

Make sure your upload_tmp_dir directive is set correctly in php.ini.  It is most likely set to "no value."

ebousillah at hotmail dot com
10-Jan-2003 10:54

[[Editors note: This applies to any PHP directive when running as a module SAPI (not cgi or cli)]]
If you changed your MAX_FILE_SIZE just DON'T FORGET to restart your apache server!  Just a tip :)

20-Jan-2003 03:55
PPL check chmod of dir you are uploading to, it must be 777 in order to make it accept uploads!

Thanx the people on the board, really making the difference.

tim at rawnet dot com
20-Jan-2003 09:29

With respect to the file_uploads directive in the php.ini, if this is set to 'off' and a form has enctype="multipart/form-data" set, then NO information will be available in the $_POST array, rather than just the file information not being available.
Stephen Borrill
31-Jan-2003 10:35

open_basedir restrictions also stop file uploads in the same way as safe mode, which is understandable. However, I don't see why you can't change upload_tmp_dir on a virtualhost basis (e.g. to point to a temp directory in the user's webspace). upload_tmp_dir is marked as being PHP_INI_SYSTEM though which means it doesn't work for virtualhosts.
Augusto L�dtke (auglud at terra dot com dot br)
04-Feb-2003 05:37

[Editor's Note]
if you call your the field eg. 'important_file' then, instead of $_FILES['userfile'] you will get the global $_FILES['important_file']

That's all the difference there is,
also notice that with register globals on, the array would be called $important_file and $important_file_type, etc.
[/Note]

In the file upload form, the name of the field must be "userfile" or it will not work.
To copy the file to the same directory where the script is you can use:

move_uploaded_file($_FILES['userfile']['tmp_name'],
dirname($_SERVER['PATH_TRANSLATED']).
"/".$_FILES['userfile']['name']);

dkalafus at removethis dot stanford dot thistoo dot edu
12-Feb-2003 12:15

On uploading files in safe mode:

We were getting errors when trying to move uploaded files with move_uploaded_file():

 [error] PHP Warning:  Unable to access destinationdirectory/filename.gif

This despite having the same uid/gid for the php script AND the destination directory, with the destination directory mode 777.  Even specifying an upload directory with the same uid/gid didn't work.

Turned out that using copy() instead of move_uploaded_file() works fine.  Don't know why. (Using PHP 4.2.2)

someone at anticapslock dot com
12-Feb-2003 09:22

[[Ed note: Mention that $_REQUEST no longer contains FILES as of PHP 4.3.0]]
On my server $_REQUEST contained the same info as $_FILES does, so I used those variables when developing. However, on my webhost, $_REQUEST did not contain the upload information. Took some time to find the problem...

root at titleofsite dot com
24-Feb-2003 12:52

Going half crazy figuring out why file uploads weren't working with Internet Explorer on Win XP I found out after reading jim.dam's post that IE sends a different file-type for jpgs: image/pjpeg instead of image/jpeg. Very nice.
So when checking for file type you should always consider different MIME types for the files. .jpg could also be image/jifi for example. Or don't rely on file types at all and check the extension instead.

donkey at example dot com
01-Mar-2003 04:06

I was going barmy trying to get the upload example working on my localhost!

It was giving errors to the tune of "cannot create file, it is a directory"

Having read all the threads, I couldn't still figure out how to. Then I thought why not read move_uploaded_file() documentation and there it was:

"bool move_uploaded_file ( string filename, string destination)

This function checks to ensure that the file designated by filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload mechanism). If the file is valid, it will be moved to the filename given by destination. "

The important thing is: "If the file is valid, it will be moved to the filename given by destination." which makes the bulb light.

Here is my code:

<?php
// In PHP earlier then 4.1.0, $HTTP_POST_FILES should be used instead of $_FILES.
// In PHP earlier then 4.0.3, use copy() and is_uploaded_file() instead of move_uploaded_file

$uploadfile = $_FILES['userfile']['tmp_name'];
$uploaddir = $_SERVER['DOCUMENT_ROOT'] . '/path/to your dir/' . $_FILES['userfile']['name'];

print "<pre>";
if (move_uploaded_file($uploadfile, $uploaddir)) {
   print "File is valid, and was successfully uploaded.  Here's some more debugging info:\n";
  print_r($_FILES);
} else {
   print "Possible file upload attack!  Here's some debugging info:\n";
  print_r($_FILES);
}
?>

If you are using a windows server, refer to the related post above for '/path/to your directory/'

As many people mentioned above, remember to do a chmod -c -v 0777 on the directory you want your uploaded files to be moved to.

In the hope that this helps someone pulling his/her hair,

Donkey.

PS Thanks for everyone who helped by posting here.

ov at xs4all dot nl
09-Mar-2003 02:08

This took me a few days to find out: when uploading large files with a slow connection to my WIN2K/IIS5/PHP4 server the POST form kept timing out at exactly 5 minutes. All PHP.INI settings were large enough to accomodate huge file uploads. Searched like hell with keywords like "file upload php timeout script" until I realised that I installed PHP as CGI and added that as a keyword. This was the solution:

To set the timeout value:
1. In the Internet Information Services snap-in, select the computer icon and open its property sheets.
2. Under Master Properties, select WWW Service, and then click the Edit button
3. Click the Home Directory tab.
4. Click the Configuration button.
5. Click the Process Options tab, and then type the timeout period in the CGI Script Timeout box.

Thanks to !

ov at xs4all dot nl
09-Mar-2003 02:15

[Editor's Note]If the permissions are set incorrectly in the temporary upload directory PHP's attempt to unlink the file will fail, resulting in the file not being deleted. [/Note]

Another problem I had was that move_uploaded_file() didn't really move the file, but copied it. Setting the permissions correctly solved that:

On your WIN2K/IIS5 server:
1. Right-click the C:\PHP\uploadtemp folder
2. Check Read/Write permission to IUSR_<machine>, uncheck the remaining options.
3. Click Advanced and edit the Internet Guest account.
4. Select the option to delete subfolders and files.
5. Click OK a few times.

kern at epiware dot com
13-Mar-2003 01:58

Below is a script that will help to resolve the most coomon prolbems that are encountered when trying to to upload large files.  



Just save the script to your directory, and it will display your current PHP settings, and offer suggestions to increase your file upload size.  You can then also test the file upload process with the same script to verify. Just tested on Linux not Windows

garyds at miraclemedia dot ca
16-Mar-2003 01:12

As it has been mentioned above, Windows-based servers have trouble with the path to move the uploaded file to when using move_uploaded_file()... this may also be the reason copy() works and not move_uploaded_file(), but of course move_uploaded_file() is a much better method to use. The solution in the aforementioned note said you must use "\\" in the path, but I found "/" works as well. So to get a working path, I used something to the effect of:

"g:/rootdir/default/www/".$_FILES['userfile']['name']

...which worked like a charm.

I am using PHP 4.3.0 on a win2k server.

Hope this helps!

gm at NOSPAM dot df dot PLEASE dot ru
18-Mar-2003 01:15

Keywords: file upload problems

The PHP Online Manual describes upload_tmp_dir as follows:
"The temporary directory used for storing files when doing file upload. Must be writable by whatever user PHP is running as. If not specified PHP will use the system's default."

and in "php.ini-recommended" file this variable is commented out to apply default behavior, but this is not works as you might expect.

If we will look the source (main/php_open_temporary_file.c) at the get_temporary_dir() function, we will notice that for Windows platform detection of system temporary directory works properly, while for UNIX-like OSes it depends of the current value of TMPDIR environment variable.

Imagine, that you started up your server and, after some uptime, decided to update your Apache binaries. Let's look on TMPDIR environment variable all the way we described above:

1. Starting up the system.
The system init script will set correct value to the TMPDIR environment variable (usually, /tmp)
2. Starting up the Apache web server
Apache environment will be cloned from the current one, which, at this moment, holds correct TMPDIR value
3. Logging as root user, shutting down Apache, doing a maintance works, starting up Apache again.
This is the weakest place of described system temporary directory detection logic based on environment variable. Think, that OS is configured to provide separated temporary directories for each user (good strategy), or this user configured his system to store root's temporary directory in safe place which not intersects with other users (for example, in his home directory). So, TMPDIR for this user session will be "/root/tmp" (for example). After starting Apache, it's environment will be holding a copy of current TMPDIR. Next step, after binding to port, Apache drops it's privilegies of superuser and losts permisions to the directory pointed by TMPDIR. Oops, no file uploads possible.

Resume: set the upload_tmp_dir to your system temporary directory by hand.

Suggestion to PHP develompent team: maybe hardcoding "/tmp" as sane default is better way to get safe system temporary directory on UNIX-like OSes?

diegoful at yahoo dot com
25-Mar-2003 07:22

SECURITY CONSIDERATION: If you are saving all uploaded files to a directory accesible with an URL, remember to filter files not only by mime-type (e.g. image/gif), but also by extension. The mime-type is reported by the client, if you trust him, he can upload a php file as an image and then request it, executing malicious code.
I hope I am not giving hackers a good idea anymore than I am giving it to good-intended developers. Cheers.

master at codedarts dot irc-europa dot org
01-Apr-2003 05:10

I was trying to set up a file upload form, and after a long time trying to do a upload, I noticed that if you set the MAX_FILE_SIZE on the form, it shouldn't work. Strange, but true. Try to delete the MAX_FILE_SIZE input, it might work (and this field is ignored in many cases by php)
mightye at mightye dot org
07-Apr-2003 10:53

On Handling uploads of large files on Windows and/or storing in MySQL.

I see a couple of people suggest you do this:
$data = addslashes(fread(fopen($file['tmp_name'], "r"), ($file['size'])));

First, on Windows, you want "r" to be "rb" because the file may be binary.  Second, if this is a large file, this is a highly inefficient script.  Plus if you are storing the file in MySQL, with a large file, your query will more than likely exceed the MySQL default max size, and you will get the "MySQL has gone away" error.

What I suggest is that you handle a file in parts, with a table for the file name, mime type, file size, etc, and a separate table to hold the actual file data.  Then do something like this:

define("MAX_SQL",50000);
$fp = fopen($file['tmp_name'],"rb");//
$sql = "INSERT INTO files (`filename`,`mimetype`,`filesize`)
VALUES
('$file[name]', '$file[type]','$file[size]')";
mysql_query($sql) or die(mysql_error(LINK));
$id = mysql_insert_id();
while (!feof($fp)){
$data = addslashes(fread($fp,MAX_SQL));
$sql = "INSERT INTO filedata (fileid,filedata) VALUES($id,\"".$data."\")";
mysql_query($sql) or die(mysql_error(LINK));
}

You will want an auto incrementing field in `filedata` as you will need to order by this field to ensure that the file is reassembled in the correct order, or else add an incrementing ID in your script.

This model is many orders of magnitude more efficient than attempting to load an entire large upload in to memory all at once, and generating a huge SQL statement.  The "b" switch ensures that in Windows we don't hit a premature end of file, and the fact that we are only loading portions of the file in to memory at a time, and are passing only portions of it to the database at a time represents a significantly lower load on the server both processor wise and memory wise.  

In my testing, this later model required 5 seconds of processing time for a 100 meg file after the upload was complete, while other models timed out at my 120 second threshold before the file was completely loaded in to memory.

12-Apr-2003 09:22
I noticed with Windows/IIS and PHP that the move_uploaded_file does not seem to work (and does not produce an error either!). Instead use copy($_FILES['userfile']['tmp_name'], "./uploads/" . $_FILES['userfile']['name']);
timon at fixproject dot com
12-Apr-2003 05:30

This is my simple image upload script which manages a few things :

Renames the image when copying from temp/folder to upload/folder. I Used the user_id($id) which almost every good
programmer would use. This way 2 files can never have an name issue (overwrite).....

It checks the image matches the maximum width and height...

It checks if the image matches the maximum size rules

I think this can be useful for some specified webmasters :

// Script *************************************

$imtype=$_FILES["imgfile"]["type"];
$imsize=$_FILES["imgfile"]["size"];
$imname=$_FILES["imgfile"]["name"];
$imtemp=$_FILES['imgfile']['tmp_name'];
$immaxsize="50000";
$immaxwidth="700";
$immaxheight="700";

if ($imsize > $immaxsize){
$error_message="You Image is $imsize Bytes the maximum allowed is $immaxsize";
}

if (!$error_message){
   $imgsize = GetImageSize($imgfile);
  //== check size  0=width, 1=height
   if (($imgsize[0] > $immaxwidth) || ($imgsize[1] > $immaxheight)){
    $error_message="Your image width and height allowed is $immaxwidth by $immaxheight px. Yours did not match this rule";
}
}// end if error_message
if (!$error_message){
if ($imtype == "image/x-png"){
$extension=".png";
}elseif ($imtype == "image/pjpeg"){
$extension=".jpg";
}elseif ($imtype == "image/gif"){
$extension=".gif";
}else{
$error_message="Please upload images with the extension .jpg or .jpeg or .gif or .png only";
}
}//end if error_message
if (!$error_message){
if (is_uploaded_file($imtemp)){
      copy($imtemp,"$uploaddir/".$id."$extension");
      unlink($imtemp);
    } else {
      $error_message="You did not match our Security Settings !";
  }
}// END IF ERROR MESSAGE IS EMPTY & PICTURE SETTINGS

if ($error_message){
require ("$dir[func]/error_check.php");
error_check($error_message);
exit;
}else{
profile_save_message();
}

// End Script ************************************

14-Apr-2003 08:45
It's probably been said before, but

DON'T FORGET enctype="multipart/form-data"

in your form tag, or your file upload will not work.

ie:
<form enctype="multipart/form-data" action=form.php method=put>

Hope it saves you some frustration!

Richard
18-Apr-2003 11:51

If you're using Apache 2, you may have to comment out the following lines in your Apache config

SetOutputFilter PHP
SetInputFilter PHP

With these in, my binary files were incorrectly uploaded

18-Apr-2003 04:31
You might want to replace all occurrences of "$_FILES['userfile']['name']" with "basename($_FILES['userfile']['name'])" or something similar to prevent unauthorized directory traversal.

The example used in the manual would allow anyone to provide a 'name' with '../'.

Dave
25-Apr-2003 05:56

Large file Uploading

If you use apache like my company, and need to upload large files, make sure you change the limitrequestbody option in apache. otherwise, you wont even be able to post.

young
13-May-2003 02:54

using apache on a linux box.
is_uploaded_file and move_upload_file and copy would return true. but i still couldn't find the file.
i set /tmp as the upload dir in php.ini, but /tmp was an alias to /var/tmp.  changing the upload dir in php.ini to /var/tmp fixed it. and it's working fine now.

wonko at nulldevice dot com
20-May-2003 09:18

One thing that many people seem to overlook (I know I did) is in the php.ini - in addition to the  max_post_size there is also upload_max_filesize - which defaults to 2MB.  If you want to upload anything larger than that, you'll need to adjust that as well as the max_post_size and the MAX_FILE_SIZE.
add a note add a note

<CookiesFile-upload errors uitgelegd>
 Last updated: Tue, 22 Apr 2003
show source | credits | mirror sites 
Copyright © 2001-2003 The PHP Group
All rights reserved.
This mirror generously provided by: /
Last updated: Sat May 24 21:09:36 2003 CEST