00:00
00:00
Newgrounds Background Image Theme

Our goal is for Newgrounds to be ad free for everyone! Become a Supporter today and help make this dream a reality!

PHP: file uploads

10,296 Views | 66 Replies
New Topic Respond to this Topic

PHP: file uploads 2005-11-04 00:02:54


When using php for file uploads, there are a few prechecks you need to make sure of. This is perhaps the most important step to ensure that the file upload process is fluently fulfilled. To check to make sure that file uploads are enabled, you can (if possible) reference your server's php.ini file. Check to see if the file_upload directive is set to true, meaning its value is 1. If you are running a version of php which is older than 4.0.3 this directive is not present in the php.ini file.

You may also check the upload_max_filesize and other directives to see the limitations of your file uploads. If you're wanting to limit the filesize with this configuration directive, you can use an integer to represent the maximum filesize or you can use shorthand notation. In integer representation, you specify the maximum filesize (in bytes) that the server should accept. In shorthand notation you can use K, M, and G abbreviations which represent Kilobyte, Megabyte, and Gigabyte, respectively. However, remember that these shorthand notations are only available in php versions 5.1.0 and higher. If you have further questions about these commonly used directives you can consult the php.net file upload configuration help, because it is no longer discussed in this tutorial.

If you know a thing or two about the upload system, you can change the upload_tmp_dir directive. This directive allows you change the path that files are temporarily stored in while being uploaded. If you know about this then you can continue to use it; however, if you aren't familiar with what I'm talking about, don't sweat it because we won't talk about it and nor do we need to discuss it to make this tutorial successful.

Note: If you are changing this make sure that the directory is writable.

Now that we've looked at some of the configuration precautions, we'll look at the HTML and PHP that makes this very useful tool possible. If you don't know HTML then don't worry about learning it from this tutorial, because I will only discuss the necessary parts of the <form> tag to make the upload system functional.

Here is my example code for upload.html as I have named my file. It doesn't matter what you name your file, just remember it for linking and what not.

upload.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-tr
ansitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Upload System</title>
</head>
<body>
<form name="file_uploader" action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="data"><br />
<input type="submit" name="upload" value="Upload File">
</form>
</body>
</html>

Now, you may notice that the enctype parameter of the <form> tag is set to multipart/form-data. This is the necessary setting for this if you wish to enable file uploads in the HTML form. If you do not have the enctype specified, or it is not set to multipart/form-data, then the upload will not work.

Okay, here comes the juicy part of the tutorial, the PHP code to make the upload work.
upload.php
<?php
# Check to see if the file is accessible
if ( !isset($_FILES['data']['name']) || $_FILES['data']['name'] == '' ) {
die('No input file specified. Please go back and select a file to upload.');
} // End check for file being set

$max_filesize = 999999;
$filetype = 'text/plain';
$upload_path = '/ngbbs/';

# Check to see if the filesize is too large
if ($_FILES['data']['size'] > $max_filesize) {
die('Your filesize is too large. Please make your filesize smaller than ' . $max_filesize . ' bytes.');
} // End if filesize is too large

# Check to see if the filetype is correct
if ($_FILES['data']['type'] != $filetype) {
die('Sorry, your file was not of the ' . $filetype . ' mimetype (yours was ' . $_FILES['data']['type'] . ').');
} // End filetype check

# If file has gotten this far, it is successful

$copy_to = $_SERVER['DOCUMENT_ROOT'] . $upload_path . $_FILES['data']['name'];

# Upload the file
$upload = move_uploaded_file($_FILES['data']['tmp_na
me'], $copy_to);

# Check to see if upload was successful
if (!$upload) {
die('Sorry, your file could not be uploaded.');
}

echo 'Your file contents are below: <hr>' . file_get_contents($copy_to);
?>

Okay, now it's time to explain the pieces of code you see in front of you. The $_FILES (or $HTTP_POST_FILES in long form) superglobal holds the contents of the file that was uploaded just as $_POST (or $HTTP_POST_VARS in long form) and $_GET (or $HTTP_GET_VARS in long form) hold POST and GET variables, respectively. The first key of the array superglobal should be the name of the HTML file field which is being uploaded. In our case, I named the HTML field data so all the calls to $_FILES begin with the data element. Secondly, the other key you are accessing is the information you would like to retrieve about the file.

$_FILES['html_name']['name'] retrieves the file's name on the user's computer
$_FILES['html_name']['size'] retrieves the file's size in bytes
$_FILES['html_name']['type'] retrieves the file's mime type
$_FILES['html_name']['tmp_name'] retrieves the actual file itself

The checks are easy, but the most complicated part of the script is dealing with the upload. The path you are specifying to upload should be a path relative to your server's document root. Make sure that the path you are uploading to is writable, you may want to check CHMOD values.

The move_uploaded_file() function takes two parameters, the original file (being $_FILES['html_name']['tmp_name']) and the path you want to upload it to. This is pretty simple, since the steps are shown in detail in the code itself. This function is only available in versions 4.0.3 and higher. If you are running an older version you may want to use the copy() function instead, which requires identical arguments. The move_uploaded_file() and copy() functions return TRUE if successful and FALSE if unsuccessful. This makes it easy to determine if the file should be retrieved or stored in a database (or however you're managing the uploads) or discarded.

For the full package download please visit http://www.mustywind..com/ngbbs/upload.zip


Merkd.com - It Pays to Play

Earn real money by betting and investing; or, sponsor, challenge, compete,

recruit, communicate, network, earn money playing games, and much more.

Response to PHP: file uploads 2005-11-04 08:57:32


Time for a lesson in how to make it secure.
1. Make sure that the name doesn't contain "..", or more generaly fix the path to a specific part of the filesystem.
2. Make sure that the script doesn't copy nonuploaded files(pd's script is safe at this point, because he's useing move_uploaded_file).
3. Don't relay on the mimetype, it's easily spofed. Check the file extension instead.


Each time someone abuses hittest, God kills a kitten. Please, learn real collision testing.

Response to PHP: file uploads 2005-11-04 10:57:25


At 11/4/05 08:57 AM, henke37 wrote: Time for a lesson in how to make it secure.
1. Make sure that the name doesn't contain "..", or more generaly fix the path to a specific part of the filesystem.

I ran out of characters to type in the textarea. Anyway, you can easily escape those with a few replaces and what not. This was just the basics of a file upload. I'm creating another one on securing input information. Not just files, but all input information.

2. Make sure that the script doesn't copy nonuploaded files(pd's script is safe at this point, because he's useing move_uploaded_file).

Well, there is actually an is_uploaded_file function as well. Read up on php.net's documentation and you'll see useful stuff for this.

3. Don't relay on the mimetype, it's easily spofed. Check the file extension instead.

Not instead of but along with. I had to delete that for simplicity and what not. Like I said, don't comment on how insecure it is, because I'm making another tutorial that shows how to make information secure.

It works, I've tested it, it's a basic upload system as explained previously. I'll tell more advanced shit today.


Merkd.com - It Pays to Play

Earn real money by betting and investing; or, sponsor, challenge, compete,

recruit, communicate, network, earn money playing games, and much more.

Response to PHP: file uploads 2005-11-04 11:25:09


oh... so I shouldn't just be using 'copy' to move my temp file to a permenant place on the server


BBS Signature

Response to PHP: file uploads 2005-11-04 15:58:51


At 11/4/05 11:25 AM, Afro_Ninja wrote: oh... so I shouldn't just be using 'copy' to move my temp file to a permenant place on the server

Well, it won't hurt. However, you can use is_uploaded_file() which returns a boolean value depending if the file was uploaded via HTTP POST.

For instance, like this:
if ( !is_uploaded_file($_FILES['html_name']['tm
p_name']) ) {
echo 'Upload attack';
}


Merkd.com - It Pays to Play

Earn real money by betting and investing; or, sponsor, challenge, compete,

recruit, communicate, network, earn money playing games, and much more.

Response to PHP: file uploads 2005-11-04 16:58:10


Great tutorial man! I downloaded the file and put it on my website but everything I submitted was too big a file! :P

Response to PHP: file uploads 2005-11-04 17:12:54


I also only check the mime type, not the file extension. The files I upload are renamed and have the gif or jpeg extension tacked onto them, depending on which mime type was detected. Could someone spoof it and upload something malicious to my server?


BBS Signature

Response to PHP: file uploads 2005-11-04 17:55:37


When I upload a file, I always get this error: (The upload error that you made:)
No input file specified. Please go back and select a file to upload.

I mean, the uploader won't upload the file.


BBS Signature

Response to PHP: file uploads 2005-11-04 18:41:23


Doofy, I've made uploaders before, and I've made one successfully upload and insert into a MySQL db and all, but it was a special case, as It was on a dedicated server, and I had direct access to the php.ini. However, I'm not always so lucky. I normally develop on virtual shared servers, and thus disallow me to change the max_filesize in the .ini file. I noticed you had a variable defined right in the file itself for the max_filesize. I've tried using an ini_set(foo); to change my ini on the fly and that didn't work either. Could you perhaps explain the workaround for the default setting of 2 Mb that apache has?

Response to PHP: file uploads 2005-11-04 18:54:36


At 11/4/05 06:41 PM, nixopax wrote: Doofy, I've made uploaders before, and I've made one successfully upload and insert into a MySQL db and all, but it was a special case, as It was on a dedicated server, and I had direct access to the php.ini. However, I'm not always so lucky. I normally develop on virtual shared servers, and thus disallow me to change the max_filesize in the .ini file. I noticed you had a variable defined right in the file itself for the max_filesize. I've tried using an ini_set(foo); to change my ini on the fly and that didn't work either. Could you perhaps explain the workaround for the default setting of 2 Mb that apache has?

That's strange. I work on a shared host too and I wrote a form that I used to upload 5-6mb flash animations. Maybe my host changed it...


BBS Signature

Response to PHP: file uploads 2005-11-04 19:00:34


Will anyone help my problem :)?


BBS Signature

Response to PHP: file uploads 2005-11-04 20:12:30


nice tutorial, very well written too, I'll be sure to use this very soon


BBS Signature

Response to PHP: file uploads 2005-11-04 21:39:14


At 11/4/05 07:00 PM, blah569 wrote: Will anyone help my problem :)?

Are you renaming the file field in the HTML form? Download the packet from my website and it should work.


Merkd.com - It Pays to Play

Earn real money by betting and investing; or, sponsor, challenge, compete,

recruit, communicate, network, earn money playing games, and much more.

Response to PHP: file uploads 2005-11-05 00:52:59


I did, I get a diffrent error (a coding error), but when I do it on my server, It won't let me upload anything.

This is what I have for upload.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-tr
ansitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>PHP Upload System</title>
</head>
<body>
<form name="file_uploader" action="upload.php" method="post" enctype="multipart/form-data">
<input type="file" name="data"><br />
<input type="submit" name="upload" value="Upload File">
</form>
</body>
</html>

And this is what I have for upload.php:
<?php
# Check to see if the file is accessible
if ( !isset($_FILES['data']['name']) || $_FILES['data']['name'] == '' ) {
die('No input file specified. Please go back and select a file to upload.');
} // End check for file being set

$max_filesize = 999999;
$filetype = 'text/plain';
$upload_path = '/ngbbs/';

# Check to see if the filesize is too large
if ($_FILES['data']['size'] > $max_filesize) {
die('Your filesize is too large. Please make your filesize smaller than ' . $max_filesize . ' bytes.');
} // End if filesize is too large

# Check to see if the filetype is correct
if ($_FILES['data']['type'] != $filetype) {
die('Sorry, your file was not of the ' . $filetype . ' mimetype (yours was ' . $_FILES['data']['type'] . ').');
} // End filetype check

# If file has gotten this far, it is successful

$copy_to = $_SERVER['DOCUMENT_ROOT'] . $upload_path . $_FILES['data']['name'];

# Upload the file
$upload = move_uploaded_file($_FILES['data']['tmp_na
me'], $copy_to);

# Check to see if upload was successful
if (!$upload) {
die('Sorry, your file could not be uploaded.');
}

echo 'Your file contents are below: <hr>' . file_get_contents($copy_to);
?>

I get a "Select a file for uploadin") (or somthin' like that). And yes, I have browsed a file.


BBS Signature

Response to PHP: file uploads 2005-11-05 08:48:33


You could try just checking if the file is there by checking its size instead of checking of it's set or if it doesn't have a name. Try this:

if ($_FILES['data']['size'] <= 0) {

instead of

if ( !isset($_FILES['data']['name']) || $_FILES['data']['name'] == '') {

However, I still can't imagine how that would be the problem. Could you show me the exact error? If anything I would've thought you got the "Cannot upload file" error because you didn't change the path to upload to. If you do not have the /ngbbs/ on your web tree's root then it will not work, also, /ngbbs/ must also have the proper permissions to be written to.

I just named mine /ngbbs/ because I run all my scripts on my local Apache server which I host on a Linux machine. I just created a /ngbbs/ since I knew I would going to be testing and creating a lot of scripts for the php main topic.


Merkd.com - It Pays to Play

Earn real money by betting and investing; or, sponsor, challenge, compete,

recruit, communicate, network, earn money playing games, and much more.

Response to PHP: file uploads 2005-11-05 09:06:10


The error:

No input file specified. Please go back and select a file to upload.


BBS Signature

Response to PHP: file uploads 2005-11-05 15:59:35


If the names of the HTML fields correspond to those of the php fields I can't imagine why you would or even could be getting that error.


Merkd.com - It Pays to Play

Earn real money by betting and investing; or, sponsor, challenge, compete,

recruit, communicate, network, earn money playing games, and much more.

Response to PHP: file uploads 2005-12-11 05:55:49


So I can modify the allowed extensions(text) to whatever we want, like jpg/image, right? But what if I want to allow .swf, .jpg, .gif, and .png?


BBS Signature

Response to PHP: file uploads 2005-12-11 06:20:17


At 12/11/05 05:55 AM, -Toast- wrote: So I can modify the allowed extensions(text) to whatever we want, like jpg/image, right? But what if I want to allow .swf, .jpg, .gif, and .png?

You could do this;

if ( !preg_match('#(jpg|gif|png|jpeg|swf)$#si', $files) ) {
echo "<br>- Sorry, you've uploaded a wrong file type. Allowed file types are on the index.";
}

Where $files is the variable of the file. ;-)


"Actually, the server timed out trying to remove all your posts..."

-TomFulp

Response to PHP: file uploads 2005-12-11 06:36:52


Thanks, but there's still a problem with a directory or some weird file thingy.
Upload your swfs! It says something with a directory wich does not exist, although I added a uploads directory...


BBS Signature

Response to PHP: file uploads 2005-12-11 06:38:01


Sorry, wrong link...


BBS Signature

Response to PHP: file uploads 2005-12-11 06:47:21


Whats the code? Because it's looks like you've added a / before where it's being uploaded lol.


"Actually, the server timed out trying to remove all your posts..."

-TomFulp

Response to PHP: file uploads 2005-12-11 07:12:26


I prefered not modifying it at my first try, I used doofy's code except I changed /ngbbs/ to /upload/.

Pilot Doofy once wrote:
$upload_path = '/ngbbs/';

BBS Signature

Response to PHP: file uploads 2005-12-14 07:53:08


Help...?


BBS Signature

Response to PHP: file uploads 2005-12-14 08:12:42


At 12/11/05 07:12 AM, -Toast- wrote: I prefered not modifying it at my first try, I used doofy's code except I changed /ngbbs/ to /upload/.
Pilot Doofy once wrote:
$upload_path = '/ngbbs/';

Change it to:
/toast/upload/

Or create a directory called upload from your parent directory (From: http://elementalflash.com, so http://elementalflash.com/upload). Whatever you do, make sure the directory has read write and execute permissions for everyone (Chmod 777).

Response to PHP: file uploads 2006-01-21 00:23:33


"$copy_to = $_SERVER['DOCUMENT_ROOT'] . $upload_path . $_FILES['data']['name'];

# Upload the file
$upload = move_uploaded_file($_FILES['data']['tmp_na
me'], $copy_to);"

Ok, I'm just having some trouble with these. Can someone explain what $_SERVER['DOCUMENT_ROOT'] is and what it can do. Also, are the dots inbetween $_SERVER['DOCUMENT_ROOT'], $upload_path and $_FILES['data']['name] separating each variable or is that the syntax for figuring out the upload path?

Response to PHP: file uploads 2006-01-21 00:53:07


At 1/21/06 12:23 AM, perj wrote: Ok, I'm just having some trouble with these. Can someone explain what $_SERVER['DOCUMENT_ROOT'] is and what it can do.

It contains your document root path. On shared hosting it will be /home/your account name/public_html/ usually. It is used when doing almost all directory related stuff.

Also, are the dots inbetween
$_SERVER['DOCUMENT_ROOT'], $upload_path and $_FILES['data']['name] separating each variable or is that the syntax for figuring out the upload path?

That is syntax. The full-stop character is used to join strings and/or variables.

Response to PHP: file uploads 2006-01-21 00:56:38


so those dots are the same as for something like :

echo $poo . ' is brown.'

Response to PHP: file uploads 2006-01-21 01:08:25


At 1/21/06 12:56 AM, perj wrote: so those dots are the same as for something like :

echo $poo . ' is brown.'

Yes.

Response to PHP: file uploads 2006-01-29 12:03:22


Hey I tried this out and the file size was right the mime type was right etc etc. However it returns the error 'Sorry, your file could not be uploaded.'. Why do you think this could be?


- Matt, Rustyarcade.com