Trapping file upload errors

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
inghamn
Forum Contributor
Posts: 174
Joined: Mon Apr 16, 2007 10:33 am
Location: Bloomington, IN, USA

Trapping file upload errors

Post by inghamn »

I have an attachment system working, handling file uploads. If everything goes well, the file gets uploaded, handled by PHP, and stored in it's appropriate place.

However, when the user, let's say, tries to upload something too big (in violation of upload_max_filesize) I can't seem to check for, and throw an exception or error. I get an error in my error_log, but PHP dies right then and there - without running any of my code. So the error seems to be happening during the POST and before any code is actually executed.

Is there a way to have my PHP code handle this sort of error?
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Post by superdezign »

Check for the errors.

Code: Select all

$_FILES['uploadFieldName']['error']
User avatar
inghamn
Forum Contributor
Posts: 174
Joined: Mon Apr 16, 2007 10:33 am
Location: Bloomington, IN, USA

Post by inghamn »

If there's a violation of post_max_size, then $_POST and $_FILES are wiped. So, there's no $_FILES['uploadFieldName'] array at all.
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

If the POST size is exceeded there is no way to sort this out. Increase the max post size to a larger amount than max_upload_size. This can be done in .htaccess.
User avatar
inghamn
Forum Contributor
Posts: 174
Joined: Mon Apr 16, 2007 10:33 am
Location: Bloomington, IN, USA

Post by inghamn »

Doh - sorry to answer my own question, but I've figured out the answer.

If the user does a POST from the browser, PHP will populate $_SERVER['CONTENT_LENGTH'] with the size of their POST. This will number will stick around, even if PHP wipes $_POST and $_FILES because of a post_max_size violation, or a upload_max_filesize violation.

So, for scripts where you are expecting to deal with an upload, you must check $_SERVER['CONTENT_LENGTH'] first to see if they uploaded (posted) anything. If it's bigger than post_max_size, you can have PHP display an error message, or whatever else you want to do.

Code: Select all

# Attachments handling code
# CONTENT_LENGTH will be set if there's a POST.  If it's too big, most
# likely they were trying to upload an attachment.
if (isset($_SERVER['CONTENT_LENGTH']))
{
	if ($_SERVER['CONTENT_LENGTH'] > 1000000 * (int)ini_get('post_max_size'))
	{
		$_SESSION['errorMessages'][] = new Exception('media/uploadFailed');
	}
}
# Now we can safely use $_POST and $_FILES to handle the upload
if (isset($_POST['attachment']))
{
	if (isset($_FILES['attachment']) && $_FILES['attachment']['name'])
	{
		$attachment = new Attachment();
		$attachment->setTitle($_POST['attachment']['title']);
		$attachment->setDescription($_POST['attachment']['description']);
		$attachment->addDocument($_SESSION['document']);
		try
		{
			$attachment->setFile($_FILES['attachment']);
			$attachment->save();
		}
		catch(Exception $e) { $_SESSION['errorMessages'][] = $e; }
	}
}
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Post by Mordred »

Nice solution, inghamn, only there's one issue with it:

Code: Select all

1000000 * (int)ini_get('post_max_size')
This is not correct. First, if the size is given in megabytes, you should multiply by 1048576, and second, the setting may be given in kilobytes or bytes. RTFM: http://php.net/manual/en/faq.using.php# ... thandbytes
User avatar
vigge89
Forum Regular
Posts: 875
Joined: Wed Jul 30, 2003 3:29 am
Location: Sweden

Post by vigge89 »

The following is what I use to turn the post_max_size setting into a byte value:

Code: Select all

$post_max_size = trim (ini_get ('post_max_size'));
switch (strtolower ($post_max_size{strlen ($post_max_size)-1})) {
	case 'g': $post_max_size *= 1024;
	case 'm': $post_max_size *= 1024;
	case 'k': $post_max_size *= 1024;
}
(http://www.php.net/manual/en/function.ini-get.php)
Last edited by vigge89 on Sun Jun 10, 2007 11:27 am, edited 2 times in total.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

inghamn wrote:If there's a violation of post_max_size, then $_POST and $_FILES are wiped. So, there's no $_FILES['uploadFieldName'] array at all.
This is not correct. $_FILES['foo']['error'] would contain an error code, and it would not clear $_POST or $_GET.
Post Reply