8

I'm using apache, PHP.

So, for php, even I set max file size, if someone upload a huge file, it will upload the whole thing to server, and then PHP return error. is that right?

I would like the web server or PHP to stop when the file size or the request size is larger than certain size.

is there a way to do it? I remember something like setting post_max_size or setting something in apache.conf but not sure if it will stop when the file goes over the max limit.

  • I don't trust client side validation. so, I'm looking for either apache or php level solution. :)
murvinlai
  • 48,919
  • 52
  • 129
  • 177
  • Client-side validation is very user-friendly, look at HTML5 File API. It does of course need server-side validation in addition. – Flimm Aug 12 '16 at 18:22

7 Answers7

4

Apache's LimitRequestBody, afaik, it just stops the connection when going over....

Wrikken
  • 69,272
  • 8
  • 97
  • 136
  • 5
    This works, but gives you an Apache error page rather than passing control to PHP. The error is code 413 and can be handled by an `ErrorDocument` option. However, an odd Apache bug in some versions will cause the requested page to be returned *in addition* to the error document. Wild! – Cal Jan 27 '12 at 23:55
  • To add to the fun, some Apache versions will skip the error page and just hard-close the connection when the limit is reached. Some versions will show the error up to a certain size above the limit, but close the connection at some other (arbitrary) limit. – Cal Jan 27 '12 at 23:58
  • Well, don't run it on broken Apache's then :P You are right of course, it is indeed not very user-friendly. It does however fit the bill of _"I would like the web server or PHP to stop"_, opting for the first. Save for putting some proxy in front of the webserver, I wouldn't know another method. – Wrikken Jan 28 '12 at 00:00
  • And if I was so paranoid to lower `LimitRequestBody` considerable, I would be happy with hard-closing actually, although it does violate HTTP protocol. I suspect the arbitrary limit has to do with how chunks are read from the input stream, with a certain amount of bytes read in 1 go going over the limit. – Wrikken Jan 28 '12 at 00:03
  • Yeah. Aside from writing an apache module to do it more gracefully, I think this is the best way of just stopping. – Cal Jan 28 '12 at 01:38
  • Cal: Yes.. I am looking at the apache log and see if I can send event back to PHP if it sees any error like that. But.. it is no easy. :( and I can't customize the size limit for different requests. – murvinlai Jan 29 '12 at 02:19
  • 1
    I use `LimitRequestBody` in combination with `ErrorDocument 413 http://error-message-url-here/` - works well, thanks! – taber Dec 18 '12 at 10:24
  • The LimitRequestBody directive does not seem very reliable. Apache seems to stop the transfer at various random lengths. Running 2.2.22. – flm Mar 27 '13 at 15:33
2

It's not possible to stop this from the server side - the file will still be uploaded before PHP decides whether to reject it. You'd need to add that detection on the client side. While you can't do this with a regular HTML form, flash uploaders can find out the filesize before the upload starts.

On the server side, you can't do anything useful with PHP - the files have always already been fully uploaded before PHP has a chance to say 'no'. To block upload (that is, disconnect the client part way through the POST), you'll need some web server magic lower down the stack. Perlbal is capable of doing this. Writing your own Apache module is a (brute force) solution. Using any kind of lightweight proxy in front of your main web server is the solution if you're worried about big uploads tying up web server resources.

It really depends why you want to limit large uploads. If it's to save users time, just add messaging that specifies max file size. If it's server resources, use a lightweight proxy in front of the server. If it's something else, well, what is it?

Cal
  • 7,067
  • 25
  • 28
  • 1
    never ever do client side validation – ordag Jan 27 '12 at 22:25
  • The server can stop downloading when it wants. I bet there's a solution, I'm just not sure how low level it will be. – Brigand Jan 27 '12 at 22:27
  • 15
    @ordag, never ever *depend* on client side validation ;-) – Brigand Jan 27 '12 at 22:28
  • 1
    The reason is, we don't even want the file stored locally in the tmp. PHP will store the images in /tmp before the application itself inspecting it. It would be much better if I can detect the http request size and reject it if over limit. :) – murvinlai Jan 29 '12 at 02:18
2

max_execution_time and max_input_time These settings define the maximum life time of the script and the time that the script should spend in accepting input. If several mega bytes of data are being transfered max_input_time should be reasonably high. You can override the setting in the ini file for max_input_time by calling the set_time_limit() function in your scripts.

This is taken from http://www.radinks.com/upload/config.php

If you set lower values for these ini entries the script should timeout before the upload has completed

Shawn Barratt
  • 472
  • 3
  • 9
  • 1
    max_execution_time does not include file uploads at all. max_input_time is only *parse* time, which is typically sub-second even for multi-gigabytes uploads. These settings do not help here. – Cal Jan 27 '12 at 23:08
1

Use a hidden field called MAX_FILE_SIZE with a value indicating the max file size in bytes. See Example #1 on this page for further information.

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>
Flimm
  • 136,138
  • 45
  • 251
  • 267
ba0708
  • 10,180
  • 13
  • 67
  • 99
  • 3
    `MAX_FILE_SIZE` is only a voluntary user indicator so browsers can warn clients, it is by no way enforced/enforceable. – Wrikken Jan 27 '12 at 23:36
  • That is what I originally thought, but the PHP manual led me to think that the upload was discarded immediately if it was too large. In a way it makes sense if this is not the case, but it depends which "meta data" is sent about the file. I apologize for the incorrect information. – ba0708 Jan 28 '12 at 09:18
  • This doesn't do anything as far as browsers are concerned, all that it does is send an additional value in the POST data. See http://stackoverflow.com/q/1381364/247696 – Flimm Aug 12 '16 at 17:26
0

Use a timer (timeout) for each upload with a session progress feature in PHP 5.5 and measure the average time per size of the upload.

moderns
  • 650
  • 10
  • 23
0

Here is a simple jquery solution How to check file input size with jQuery? But client side validation can be hacked easily.

Community
  • 1
  • 1
Ernest Marcinko
  • 405
  • 3
  • 12
0

Use $_FILES in php.

if($_FILES['name']['size'] > $limit){
// continue;
}