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
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);
}
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.
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.
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.
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.
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.