Page 1 of 1
Trapping file upload errors
Posted: Wed Jun 06, 2007 2:29 pm
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?
Posted: Wed Jun 06, 2007 4:15 pm
by superdezign
Check for the errors.
Code: Select all
$_FILES['uploadFieldName']['error']
Posted: Thu Jun 07, 2007 7:35 am
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.
Posted: Thu Jun 07, 2007 8:46 am
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.
Posted: Fri Jun 08, 2007 2:49 pm
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; }
}
}
Posted: Sat Jun 09, 2007 2:41 pm
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
Posted: Sun Jun 10, 2007 10:05 am
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)
Posted: Sun Jun 10, 2007 10:30 am
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.