We have a new website (We've moved)! So go check out Phosphorus.co

The $_FILES Global Variable in PHP

Posted in PHP, Tutorials

Preview Image
The $_FILES variable in PHP is one of the more complicated global variables in PHP. With it, you can upload files to the server and find a bunch of stuff out about those files. Below is a little guide and writeup about this variable and how to use it, I hope you enjoy it.





The Different Forms of $_FILES

As I mentioned, $_FILES is a bit more complex than your average global variable. Unlike $_GET and $_POST where you may only have one set of square brackets, in most cases, $_FILES has two sets of square brackets. This is because $_FILES returns an array, and to access the contents of this array you have to use a second set of square brackets.

Basically, if you print out the $_FILES[] variable, you get something like below.

Array (
[name] => name.gif
[type] => image/gif
[tmp_name] => /a/temp/directory/where/the/file/is/stored
[error] => 0
[size] => 27290
)

Little Note: The information in the first square brackets is the name of the input you’re taking the file from, i.e. $_FILES['file'] would be from <input type=”file” name=”file” />

Okay, so as you can see, we’re given a lot of information about the file. So using our knowledge of basic PHP, we can deduce that the following is true:

$_FILES['file']['name']; // This is going to return the name
$_FILES['file']['type']; // This is going to return the type.
$_FILES['file']['tmp_name']; // This is going to return the temporary file location
$_FILES['file']['error']; // This is going to return whether or not there was an error (1 is for true, 0 is for false)
$_FILES['file']['size']; // This is going to return the file size in bytes

Okay so now that we have all this information we can do all sorts of stuff with our file uploads.

Security

This is just a quick word on the security of this function. Before we continue it should be noted that although the $_FILES[] variable itself is secure, if you leave this kind of script open to the public it’ll allow them to upload anything they want to your server, which you may not want. For that reason it’s important to maybe have this password protected or something like that.

Alternatively, if you don’t want a certain file format (a possibly malicious file type) to be uploaded, you can just check using $_FILES['file']['type'], for instance if we don’t want gifs to be uploaded:


if($_FILES['file']['type'] == "image/gif") {
      echo"Script Terminated";
      exit();
}

Making your File Uploader

Now that we have a bit of an understanding to how the $_FILES[] variable works, lets make a simple file uploader to try it all out. I’m putting this all in a file called fileuploader.php First we make a simple HTML Form:

<form action="?upload=true" method="post" enctype="multipart/form-data">
<input type="file" name="file" /><br />
<input type="submit" value="Submit" />
</form>

You’ll notice in the form tag enctype=”multipart/form-data”. This is required for the file uploader to work. The action is just where we want the form to go to, and the method is post. Since we’re directing the form to the same page, we can just add this below the form:


<?php

if($_GET['upload']) {

}

?>

All this does is checks if ?upload=true is in the url and then does whatever’s in the curly brackets if it is. Next we’re going to set a few variables (inside the curly brackets): a url to the directory we want the files to go to; the file name; the file size, and the temporary location


$url = "uploads/"; // The directory you want the uploads to go to
$file = $_FILES['file']['name']; // The file name that you uploaded.
$file_temp = $_FILES['file']['tmp_name']; // The temporary location
$filesize = $_FILES['file']['size'] / 1024 / 1024; // The file size in megabytes
$size = number_format($filesize, 3); // The file size to 3 decimal places

Next we’re going to use the function move_uploaded_file, which really does exactly what you’d expect, and moves the file you’ve uploaded.

Since the file is only in a temporary directory, we’re gonna move it to the directory we specified in the $url variable.

	if(move_uploaded_file($file_temp, $url.$file)) {
               /* move_uploaded_file:
                   First parameter is the temporary location,
                   second is the new location (plus name),
               */
		echo"You just uploaded the file <strong>".$file."</strong> ";
		echo"with a size of <strong>".$size." MB.</strong>";
        }
        else {
		echo"There's been a problem uploading your file. Please try again";
	}

?>

Overall this is going to give you something like this:


<form action="?upload=true" method="post" enctype="multipart/form-data">
<input type="file" name="file" /><br /><br />
<input type="submit" value="Submit" />
</form>

<?php

if($_GET['upload']) {

	$url = "uploads/";

	$file = $_FILES['file']['name'];
	$file_temp = $_FILES['file']['tmp_name'];
	$filesize = $_FILES['file']['size'] / 1024 / 1024;
	$size = number_format($filesize, 3);

	if(move_uploaded_file($file_temp, $url.$file)) {
		echo"You just uploaded the file <strong>".$file."</strong> ";
		echo"with a size of <strong>".$size." MB.</strong>";
	}
	else {
		echo"There's been a problem uploading your file. Please try again";

	}
}

?>

Done!

Well done, give yourself a pat on the back. Hopefully now you understand the $_FILES variable a bit better, and now you can move onto bigger and better things!


Share This

 

 
 

Author: Johnny




Johnny is the owner of Webtint and usually the sole contributer to the site (apart from the ocassional guest post).


Comments



TheWebTuts December 21, 2009 at 6:02 pm

Tutorial added to thewebtuts.com


John December 24, 2009 at 4:49 pm

The part about security needs to be expanded further.
As widely known, the mime type returned by $_FILES['file']['type'] is somewhat easily faked, and should not, nor can not be trusted alone to prevent malicious files from being uploaded.

As a php server, the most dangerous type of file being uploaded can be argued to be .php files. This being since uploaded .php files can leave the attacker in full power of the server.

Since the apache server will only handle .php files as php files, and run them through the engine, checking the actual name, and preventing files ending with .php from being uploaded, will do alot more for security than checking the mime-type.

This means that if a file named “script.txt” is uploaded, which contains php scripting, it will not run it as php, as .txt is not a registered php handle by default.

That being said, theres no limit or reason why several security measures can not be combined. Use the php commands to create security based on the application you are building.
No matter the application though, checking and changing the uploaded name of the file is important due to various exploits available.


    Johnny December 24, 2009 at 5:45 pm

    Hey John, thanks for your input, it’s all pretty valid. =]


      John August 3, 2010 at 12:32 am

      Forgot all about the above post.
      Figured I’d elaborate on a safe way of renaming the uploaded file. One of my own scripts use the following:
      $file_info = pathinfo($_FILES['Filedata']['name']);
      $newfilename = md5(uniqid(rand(), true)).’.’.strtolower($file_info['extension']);
      if (rename($path, $newfilename)) {
      .. Further code on success (I start creating thumbnails at this stage) ..
      }


      John August 3, 2010 at 12:49 am

      As for the extension, and the protection that’s needed on it, there’s two approaches – white list, OR blacklist.

      White list – safest approach. This means you will test the extension to check that it is one that you allow, like so:
      $file_info = pathinfo($_FILES['Filedata']['name']);
      $ext = strtolower($file_info['extension']);
      if (($ext == ‘jpg’) || ($ext == ‘jpeg’) || ($ext == ‘png’) || ($ext == ‘gif’)) {
      // Great success
      }

      else {
      // Return error, extension check failed.
      }

      Blacklist approach is the complete opposite – you simply check that the file does not have an extension you disallow. As such:
      $file_info = pathinfo($_FILES['Filedata']['name']);
      $ext = strtolower($file_info['extension']);
      if (($ext !== ‘php’) && ($ext !== ‘mp3′) && ($ext !== ‘html’) && ($ext !== ‘js’)) {
      // Great success
      }

      else {
      // Return error, extension check failed.
      }

      Obviously, the latter, blacklist check is most prone for vulnerability, as there might be an extension that is dangerous, that you haven’t thought of.

      Oh, and sorry Johnny, for hijacking your comment section.


Tony July 19, 2010 at 7:19 am

Hi, i am a beginner.

May i ask? You are using Method=”post”. But you are using if($_GET['upload']).

So is that a Post or Get?


    John August 3, 2010 at 12:39 am

    Even though you may be using a form with method=”post”, you can still pass in $_GET variables in the action – like above, where its action=?upload=true”

    To make you an example:

    In the above example, the php server would receive $_GET['get'] == ‘test1′, and $_POST['post'] == ‘test2′


Dr.Vet. Cumpanasu Florin August 4, 2010 at 8:53 pm

I whant to auto upload a file. I use a autosubmit with a if clause in php


Steve August 14, 2010 at 8:41 pm

Hey John, do us all a favor and STFU. Nobody cares what you think.


Andy Clarke August 22, 2010 at 9:47 am

Hi there,

Just thought I’d thank you for this tutorial. $_FILES has been one of those globals which I’ve dreaded using for a very long time but I now feel really comfortable using it. Probably the best and easiest to follow tutorial on this subject I’ve found.

Thanks



uberVU - social comments




Leave us a Comment



Put your name here:

Your email goes here:

Got a Website? Put it here (optional):

And finally, your comment:




Sponsors