is_uploaded_file

(PHP 4 >= 4.0.3, PHP 5, PHP 7)

is_uploaded_file — Tells whether the file was uploaded via HTTP POST

Description

boolis_uploaded_file
( string$filename
)

Returns TRUE if the file named by filename was
uploaded via HTTP POST. This is useful to help ensure that a
malicious user hasn't tried to trick the script into working on
files upon which it should not be working--for instance,
/etc/passwd.

This sort of check is especially important if there is any chance
that anything done with uploaded files could reveal their
contents to the user, or even to other users on the same
system.

See Also

User Contributed Notes 14 notes

Note that calling this function before move_uploaded_file() is not necessary, as it does the exact same checks already. It provides no extra security. Only when you're trying to use an uploaded file for something other than moving it to a new location.

Any script working with the temporary file $_FILES[]['tmp_name'] should call this function.

In any case where the script is modified to unlink(), rename() or otherwise modify the file that IS NOT move_uploaded_file() will not have the upload checked.

Likewise, most file operations are cached in PHP, therefore there should be minimal performance hit running is_uploaded_file before move_uploaded_file, since it will usually used a cached result for the latter.

The security benefits outweigh the microsecond difference in performance in any event, and should universally be used as soon as the $_FILES array is first entered into an application. While there may not be an immediate issue, code evolves and could quickly change this fact.

As of PHP 4.2.0, rather than automatically assuming a failed file uploaded is a file attack, you can use the error code associated with the file upload to check and see why the upload failed. This error code is stored in the userfile array (ex: $HTTP_POST_FILES['userfile']['error']).

Here's an example of a switch:

if (is_uploaded_file($userfile)) {

//include code to copy tmp file to final location here...

}else{ switch($HTTP_POST_FILES['userfile']['error']){ case 0: //no error; possible file attack! echo "There was a problem with your upload."; break; case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini echo "The file you are trying to upload is too big."; break; case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form echo "The file you are trying to upload is too big."; break; case 3: //uploaded file was only partially uploaded echo "The file you are trying upload was only partially uploaded."; break; case 4: //no file was uploaded echo "You must select an image for upload."; break; default: //a default error, just in case! :) echo "There was a problem with your upload."; break;}

Additionally, by testing the 'name' element of the file upload array, you can filter out unwanted file types (.exe, .zip, .bat, etc). Here's an example of a filter that can be added before testing to see if the file was uploaded:

Just looked at what I posted again and found several mistakes of the major and minor sort. That's what I get for posting before I finish my coffee. This should work better (i.e. should work in the first place):

It isn't mentioned anywhere that I've seen, but $filename *is* case-sensitive on Windows.It means that while C:\Windows\TEMP\php123.tmp may have been uploaded, C:\Windows\Temp\php123.tmp was not.

I found this out because I was using realpath() on the filename which 'fixed' the case (my Temp folder is in titlecase, not uppercase - thank you Vista).

Anyways, the problem was that PHP used %TEMP% to determine the destination for the uploaded file, and %TEMP% used the all-capitals version of the path. Changing it to use titlecase instead + restarting Apache fixed the problem.

Regarding topcat's suggested change, I am split on doing that. I don't like showing users errors that may give them more information than they should have (or show that I haven't provided for that particular error). But I want to know when there are errors that fall to the default case so I can fix my code. What I will typically do is write them to the error log something like this modification to metaltoad's post (takes into account the possibility of multi-line errors which error_log doesn't handle well):

if files are not getting uploaded and $_FILE array is empty ..and your code looks fine..then check php.ini file..the file_uploads option should be turned 'On' to allow file uploads. Turn it on and restart apache to have effect .