Hello everyone!

I have a form with a file dialog for users to upload a resume. As part of the validation I'm using the $_FILES array to check that the resume is less than 5MB. This works no problem.

However, my issue is when someone tries to upload a file larger than post_max_size (which in the case of the development server I am working on is 8M😎. The form blanks out and nothing happens (the file isn't uploaded and the validation isn't reached). It's as if the user hit ctrl-F5 and reloaded the page.

When I review my error log I see the following (expected) error:

[09-Mar-2012 17:33:24] PHP Warning:  POST Content-Length of 17739365 bytes exceeds the limit of 8388608 bytes in Unknown on line 0

My question is: how can I check for this and display/handle it so it's helpful to the user? A blank form doesn't say much. I have a notice on the form for users to not upload files larger than 5MB, but we all know how much users read... 😉

I guess I could try increasing the value for post_max_size, but is that really the best solution?

Any help or insight would be appreciated, thank you!

    5 days later

    I'm not sure there's any way to do this ... yet.

    PHP can't handle it, as PHP doesn't get involved until the POST occurs anyway. Javascript is available on the clientside, but think how dangerous it would be if JS had access to the local filesystem --- JS is, wisely, not allowed to know things like "how big is c:\users\myname\foo.doc".

    I hear that HTML5's file API may support this. In the meantime, I think that leaves only ActiveX to determine a file's size prior to posting.

    Of course, I may be wrong, but a little Googling shows that you're not alone with your question, and there aren't many different answers....

      <!-- max file size in bytes -->
      <input type="hidden" name="MAX_FILE_SIZE" value="500000">
      <input type="file" name="upload">
      

      print_r of $_FILES on success

      Array
      (
          [upload] => Array
              (
                  [name] => ok_filesize.txt
                  [type] => application/octet-stream
                  [tmp_name] => /private/var/tmp/php64763b
                  [error] => 0
                  [size] => 2228
              )
      
      )
      

      print_r of $_FILES on too large file

      Array
      (
          [upload] => Array
              (
                  [name] => too_large.txt
                  [type] => 
                  [tmp_name] => 
                  [error] => 2
                  [size] => 0
              )
      
      )
      

      Since people can forge their own requests, your server may still receive requests containing too large files, leading to the initial error you had. However, for anyone actually using your form you will be able to tell them about the file being too lage.

        johanafm: The problem isn't when a file exceeds the MAX_FILE_SIZE element (which is utterly useless and should never be used, to be honest)... it's when the entire POST request exceeds the post_max_size directive. That leads to a somewhat odd condition.

        @: One thing you can check is the variable $SERVER['REQUEST_METHOD']; even if a POST request exceeds the max size, this variable will still be set to the string 'POST'. Thus, if your $FILES and $POST arrays are both completely empty and yet $SERVER['REQUEST_METHOD'] is set to 'POST', you might consider generating an error message that suggests something went wrong with their submission, such as a file being too large.

          Thanks everyone for the input!

          After looking around a bit, the manual actually addresses this situation somewhat, so I have taken their approach. I'm passing a $GET variable with the form, and then checking if that is set to determine if the form has been submitted. I then check if $POST is empty and if it is then I know the file was too large and print an error accordingly.

          Would using the $_SERVER['REQUEST_METHOD'] approach be considered a better practice?

            Bonesnap;10999023 wrote:

            Would using the $_SERVER['REQUEST_METHOD'] approach be considered a better practice?

            Which color is "better", green or blue? 😉

            Either sound like a viable solution. If you've got control over the HTML of the form and can easily add a parameter in the query string, that sounds just as foolproof as checking if the request was a POST despite not having any POST'ed data.

            The one caveat with that, however, is that you need to be careful about how you write the code that processes form submissions. If a browser were to prefetch that URL (e.g. using a HEAD or GET request) or if a search engine were to crawl it, you would want to make sure that such requests don't kick off your form processing code. Using the REQUEST_METHOD, of course, ensures that you're still only considering requests where data was being POST'ed (e.g. an intentional form submission).

              bradgrafelman;10999027 wrote:

              Which color is "better", green or blue? 😉

              Green. Anyone who's seen Power Rangers knows Tommy was cooler than Billy. 😉

              bradgrafelman;10999027 wrote:

              The one caveat with that, however, is that you need to be careful about how you write the code that processes form submissions. If a browser were to prefetch that URL (e.g. using a HEAD or GET request) or if a search engine were to crawl it, you would want to make sure that such requests don't kick off your form processing code. Using the REQUEST_METHOD, of course, ensures that you're still only considering requests where data was being POST'ed (e.g. an intentional form submission).

              After I make sure the $GET variable is set and the $POST array isn't empty, I check if the submit button was clicked, so I think that covers me. I also check the $_FILES array before going through the submission process. The REQUEST_METHOD approach sounds like a good approach, though.

                Bonesnap;10999030 wrote:

                After I make sure the $GET variable is set and the $POST array isn't empty, I check if the submit button was clicked

                But isn't that the whole problem you're facing? You can't check if the submit button was clicked, because the POST contents exceeded post_max_size (thus you can't tell the difference between nothing POST'ed and too much POST'ed).

                EDIT: Also note in the past I've seen user comments that suggested you can still access the raw POST'ed data (even if it exceeds the posts_max_size directive) via either the 'php://stdin' or 'php://input' wrappers; see the manual page [man]wrappers.php.php[/man] for more info on those.

                  bradgrafelman;10999042 wrote:

                  But isn't that the whole problem you're facing? You can't check if the submit button was clicked, because the POST contents exceeded post_max_size (thus you can't tell the difference between nothing POST'ed and too much POST'ed).

                  If too much is POST'ed then the $_POST superglobal is empty, which is the same as if nothing was posted, so really it's the same result. But if it isn't empty then I can check if the submit button was clicked.

                  bradgrafelman;10999042 wrote:

                  EDIT: Also note in the past I've seen user comments that suggested you can still access the raw POST'ed data (even if it exceeds the posts_max_size directive) via either the 'php://stdin' or 'php://input' wrappers; see the manual page [man]wrappers.php.php[/man] for more info on those.

                  Hmm, interesting. I'll see if I have some time to look into this.

                    Write a Reply...