How to detect if a user uploaded a file larger than post_max_size?
Asked Answered
S

6

11

How should I go about handling http uploads that exceeds the post_max_size in a sane manner?

In my configuration post_max_size is a few MB larger than upload_max_filesize The problems I'm having are:
If a user uploads a file exceeding post_max_size

  • The _POST array is empty
  • The _FILES array is empty, and of course any error codes therein are not present.
  • No other info what kind of form post it is is accessible through theses means.

Part of the problem is that the receiving script takes different actions depending on the contents of the POST.

I do have access to the _SERVER variables and can get clues as to what happened, i.e. CONTENT_TYPE, CONTENT_LENGTH and REQUEST_METHOD. It does however seem very problematic to make guesses based on those contents.

MEMORY_LIMIT (set to 10 times the relevant sizes) and Apaches LimitRequestBody (set to unlimited) are found to not be at fault.

As it stands now I have a hard time even providing any meaningful messages to the user.

Is there any way to retain some form data to get better clues as to what has gone wrong? I'm very reluctant to move away from php.

Scalene answered 31/5, 2011 at 16:36 Comment(0)
P
10

For a simple fix that would require no server side changes, I would use the HTML5 File API to check the size of the file before uploading. If it exceeds the known limit, then cancel the upload. I believe something like this would work:

function on_submit()
{
  if (document.getElementById("upload").files[0].size > 666)
  {
    alert("File is too big.");
    return false;
  }

  return true;
}

<form onsubmit="return on_submit()">
<input id="upload" type="file" />
</form>

Obviously it's just a skeleton of an example, and not every browser supports this. But it wouldn't hurt to use this, as it could be implemented in such a way that it gracefully degrades into nothing for older browsers.

Of course this doesn't solve the issue, but it will at least keep a number of your users happy with minimal effort required. (And they won't even have to wait for the upload to fail.)

--

As an aside, checking $_SERVER['CONTENT_LENGTH'] vs the size of the post and file data might help detect if something failed. I think it when there is an error it will be non zero, while the $_POST and $_FILES would both be empty.

Practiced answered 31/5, 2011 at 17:15 Comment(4)
To be clear, I would implement this along with something like the quote in @King Skippus' answer. i.e., Use this client side solution to make people happy, and then look for the empty post on the server side and act accordingly.Practiced
This is useful. My primary concern is not being able to notify my users in an adequate manner. Any idea about support in current browsers?Scalene
@Captain Giraffe, I think every non-IE browser in common use allows you to check the file size via JavaScript like that, but I'm not exactly sure. (And again, it will gracefully degrade, so there's no harm in using this as part of your solution.) Also, see my edit for a potential way to check if an upload problem occurred.Practiced
Will it gracefully degrade one way or enhance progressively the other way? HTML brings us a lot of nice marketing terms yeeehKala
R
3

Per the PHP documentation:

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.

If you need the limit increased for a specific script, you can try ini_set('post-max-size', $size_needed);. I'm not sure if it can be overridden within a script, though; that limit is probably there to specifically keep you from doing what you're trying to do.

Randell answered 31/5, 2011 at 16:47 Comment(1)
I am happy with my limits, but not the way php reacts when those limits are exceeded. Also the GET idea is a useful one, but I would like it to be transparent to the user, and it feels "hackish".Scalene
R
1

I liked @Matthew answer, but needed a version that checked for multiple upload files.

This was my solution:

function checkAttachmentsSize() {
    var total = 0;
    var count = 0;

    jQuery('input[type="file"]').each(
        function() {
            if (typeof this.files[0] != 'undefined') {
                total+= this.files[0].size;
                count++;
            }
        }   
    );

    var word = (count > 1) ? 's are' : ' is';
    if (total > (uploadMax * 1000 * 1000)) {
        alert("The attachment file" + word + " too large to upload.");
        return false;
    }

    return true;
}

And, for completeness, here's the binding of the function to the form being submitted:

jQuery(function($) {
    $("form").submit(
        function() {
            return checkAttachmentsSize();
        }   
    });
);

NOTE:
uploadMax is a variable that I set via php after calculating the maximum size of the allowable upload.

Racoon answered 15/8, 2013 at 23:35 Comment(0)
N
1

You can solve this on the server side without resorting to a query string. Just compare the *post_max_size* setting to the expected content length of the request. The following code is how Kohana does it.

public static function post_max_size_exceeded()
{
    // Make sure the request method is POST
    if (Request::$initial->method() !== HTTP_Request::POST)
        return FALSE;

    // Get the post_max_size in bytes
    $max_bytes = Num::bytes(ini_get('post_max_size'));

    // Error occurred if method is POST, and content length is too long
    return (Arr::get($_SERVER, 'CONTENT_LENGTH') > $max_bytes);
}
Nilla answered 22/8, 2013 at 14:51 Comment(1)
I do not handle the upload myself. php does. If I could intercept the "content_length" from the browser, all would be pink unicorns and butterflies. I appreciate your input though.Scalene
C
0

You may need to revert to something that uses flash/silverlight etc. such as: http://www.plupload.com/

Or look at a Java-based solution...

Basically something that will break the upload into more managable (and resumable) chunks, and then re-assemble them on the server side.

Cantankerous answered 31/5, 2011 at 16:44 Comment(0)
C
0

Unless your upload form has fields other than the file input field, then $_POST should be empty - files are handled exclusively through the $_FILES. It's very odd that $_FILES would be empty if the post size is exceeded - the upload handlers have a specific error code (1/UPLOAD_ERR_INI_SIZE) to report such a condition. Also check that memory_limit is larger than the upload_max_filesize.

Your webserver may be blocking the upload as well, which would occur before PHP is invoked. On Apache, it's controlled by LimitRequestBody.

Cyrillic answered 31/5, 2011 at 16:44 Comment(2)
Yes a few other fields that under normal circumstances are there to identify what kind of upload it is. LimitRequestBody is set way above the php settings in this case and is not interfering.Scalene
Yes, I too am very surprised to find the _FILES empty just because of this.Scalene

© 2022 - 2024 — McMap. All rights reserved.