Check for upload file size too large is not working

EDIT: I found this info here:

post_max_size int

Sets max size of post data allowed. This setting also affects file upload. To upload large files, this value must be larger than upload_max_filesize. Generally speaking, memory_limit should be larger than post_max_size. When an int is used, the value is measured in bytes. Shorthand notation, as described in this FAQ, may also be used. If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty. This can be tracked in various ways, e.g. by passing the $_GET variable to the script processing the data, i.e. <form action="edit.php?processed=1">, and then checking if $_GET[‘processed’] is set.

In my php.ini I have memory_limit = 128M, post_max_size = 50M and upload_max_filesize = 25M

The "file too large message doesn’t get displayed I think, because “$_FILES superglobals are empty.” when the file size is > post_max_size (= 50M) I was trying with a 91MB file.

If I set if ($_FILES[‘my_upload’][‘size’] > 19000000) , then if I try to upload say, 21MB, I see my error message correctly.

Only when the upload size is > post_max_size is there a problem. How to get around that?? I don’t understand the tip they give.

END OF EDIT

I have a form where students can upload homework. The homework is recordings, MP3s.

I have this to check if the file is too small, works fine, goes back to the form and displays the error message:

//set a limit to the file minimum size
  	if ($_FILES['my_upload']['size'] < 150000) 
  	{
		$_SESSION['error'] = "错误!! <br>	
		The file you are sending is too small. <br>
		Your file should be more than 150KB. <br>
		This is cannot be the homework. <br>
		Please check the file you are sending and send again. <br>
		Your file could not be sent. <br>";
		//include "/uploadFiles20BE/uploadessays_pairs_V1.html.php";
		header('Location: /uploadFiles20BE/uploadessays_pairs_V1.html.php');
  		exit();        
    }

but if I try a file which is too big, well, it doesn’t get uploaded, but I don’t get the error message, I see a wrong version of my success message. The correct version should show the students’ names and numbers and says “Success! You file was successfully uploaded” Normally the files will not be more than about 8MB

//set a limit to the file upload size
  	if ($_FILES['my_upload']['size'] > 19000000) 
  	{
		$_SESSION['error'] = "错误!! <br>	
		The file you are sending is too big. <br>
		The maximum size should be less than 20MB <br>
		Please send a smaller file or send the file in an email. <br>
		Your file could not be sent. <br>";
		//echo '$_FILES[\'my_upload\'][\'size\']' . $_FILES['my_upload']['size'];
		//echo '<br><br>';
		//echo '$_SESSION[\'error\'] is ' . $_SESSION['error'];
		//include "/uploadFiles20BE/uploadessays_pairs_V1.html.php";
		header('Location: /uploadFiles20BE/uploadessays_pairs_V1.html.php');
  		exit();        
    }

Any tips as to why the ‘too large’ check is not working please?

Because the $_FILES (and $_POST) arrays are empty in this case, your post method form processing code must (always) detect this condition, before trying to use any files/post form data (hackers also send large post data to try to trigger errors in your code, so, this condition can occur even when not uploading files.)

Firstly, your code and lack of php errors indicates a few problems -

  1. Php’s error related settings are not setup to either display or log ALL php errors, including php startup errors. You should be getting undefined index errors from the posted code when this condition occurs and php has a specific startup error for this condition.
  2. You are probably not first detecting if a post method form was submitted before running any of the form processing code.
  3. Your form and form processing code are on separate pages, based on the session variable and redirect, resulting in more code and a poor User eXperience (UX.). When they are on the same page, your code should just continue on to redisplay the html document, display the error messages, and redisplay the form, repopulating the post fields with existing values, when there are user/validation errors. The only redirect you should have in the post method form processing code, is upon successful completion, to the exact same URL of the current page to cause a get request for that page.

The technically best way of detecting this condition, after you have detected if a post method form was submitted, is to compare the post_max_size setting to the $_SERVER['CONTENT_LENGTH'] value. You can get the current post_max_size setting using - ini_get('post_max_size'). Unfortunately, the post_max_size setting can be using K/k, M/m, or G/g shorthand notation, while the content length is in bytes. To compare them, you must convert the post_max_size setting to an integer. Here’s a function to do this -

// convert numbers using K/k,M/m,G/g notation to actual number
function return_bytes($val) {
    $val = trim($val);
    $last = strtolower($val[strlen($val)-1]);
    switch($last) {
        case 'g':
            $val *= 1024;
        case 'm':
            $val *= 1024;
        case 'k':
            $val *= 1024;
    }
    return $val;
}

You can then compare the two values and setup a message for the user that the total size of the form data was too large and could not be processed.

1 Like

@phdr Thanks for the reply!

I have a file called upload1file2_pairs_v1.php, at the top of which is:

if(isset($_POST['sendAnswers'])){
		$studentnr1 = $_POST['sn'];
		$studentnr2 = $_POST['psn'];

Is that not checking whether or not the form was submitted?

apache logs everything, I get a lot of undefined index errors, because students often forget to fill in a blank, or click a radio button. All get logged in /var/log/apache2/mydomain.com-error.log

You are correct that the form and processing php are not on the same form.

I thought that is how it should be.

The user clicks the submit button:

<input id="subBtn" type="submit" name="sendAnswers" value="Send your answers">

and upload1file2_pairs_v1.php takes over.

I can just write the value of post_max_size, because I won’t change that. Already too big for my liking, but, I only use 2% of my allotted 20GB cloud server space, so not really a problem.

Anyway, thanks for the tips, I will try and integrate your function in my upload1file2_pairs_v1.php and see if I can catch the error when the upload is bigger than post_max_size.

That’s not the same as detecting if a post method form was submitted. That’s checking if your submit button is set, which it won’t be when the post max size has been exceeded, since the $_POST array will be empty. It also won’t be set, depending on how the form gets submitted, in some browsers/browser-versions and it won’t be set if you use javascript/ajax to submit the form.

Detecting if a post method form was submitted looks like -

if($_SERVER['REQUEST_METHOD'] == 'POST'){

This is general-purpose and will always tell you if a post method from was submitted, even for the case of exceeding the post max size setting. If you have a case where there is more than one form processing code on a page, you would use a hidden form field with a different value for each form, then use the value of the hidden field in the form processing code to control which code to execute.

Don’t do this either. All that is doing is wasting your time typing a line of code for every form field. Instead, keep the form data as an array, then operate on elements in the array throughout the rest of the code. This will allow you to dynamically process the data, such as trimming all the data using a single line of code, validating data, building sql queries, populating html templates, without writing out code for each field.

Empty form fields don’t produce php errors, assuming you have detected if the form has been submitted before referencing the field value. Unchecked checkbox/radio buttons do produce php errors and you should use isset() statements in these cases to prevent php errors.

Perhaps, not. make sure that display_startup_errors is set to ON, on your system.

No. This results in a lot of extra code, that you have to write and maintain, and it (usually) results in validating one input at a time. By putting the form and the form processing code on the same page, it greatly simplifies all the code and allows you to validate all the inputs at once. It also allows you to repopulate the form field values, so that the student doesn’t need to keep reentering them, which actually increases the likelihood of mistakes.

That’s not the problem or the solution. Whatever value you set post_max_size to, anyone can submit data that’s larger. This occurrence is out of your control. Your code MUST detect and handle the case where the post max size value has been exceeded.

Ok, thanks for the tips. Summer break is coming soon, I will polish my PHP!

Sponsor our Newsletter | Privacy Policy | Terms of Service