简体   繁体   中英

MAX_FILE_SIZE in PHP - what's the point?

I was trying to make a file upload form and checked the PHP documentation to refresh my memory on the subject. Here is a link to the relevant article. All of a sudden I noticed this message:

The MAX_FILE_SIZE hidden field (measured in bytes) must precede the file input field, and its value is the maximum filesize accepted by PHP. This form element should always be used as it saves users the trouble of waiting for a big file being transferred only to find that it was too large and the transfer failed. Keep in mind: fooling this setting on the browser side is quite easy, so never rely on files with a greater size being blocked by this feature. It is merely a convenience feature for users on the client side of the application. The PHP settings (on the server side) for maximum-size, however, cannot be fooled.

OK... Say what? First it tells that it must precede the file upload field. Then it tells us that it is merely for convenience. And besides - it's on client side anyway so anyone can mess with it. After googling around I also found information that there are no known browsers that support it.

WTF? Why is it said that it must precede the file upload field if it seems to be (for all intents and purposes) absolutely pointless? Should I bother putting it in my HTML at all?

After failed attempt to find any authoritative information about MAX_FILE_INFO i've decided to resort to drastic measures - and peeked at PHP's holy source.

I scanned entire PHP source recursively using grep:

grep -ri MAX_FILE_SIZE .

The only place that mentioned this variable was (excluding tests folder) - rfc1867.c file. Completely expectable since rfc1867 standard deals with file uploads.

Related C code:

......
if (!strcasecmp(param, "MAX_FILE_SIZE")) {                                                                                                                                                                              
   max_file_size = atol(value);
}
......
......
if (PG(upload_max_filesize) > 0 && (total_bytes+blen) > PG(upload_max_filesize)) {
    cancel_upload = UPLOAD_ERROR_A;
} else if (max_file_size && ((total_bytes+blen) > max_file_size)) {
    cancel_upload = UPLOAD_ERROR_B;
} else if
....

So - here's short explanation of above code:

1) first we get the value of MAX_FILE_SIZE into max_file_size variable.

2) Then we check if max_file_size value exists and if the sum of already accepted bytes (total_bytes) + the size of bytes in the buffer(blen) exceeds max_file_size.

3) If 2 is true - at this point we cancel upload with some error code that's been set by this constant: UPLOAD_ERROR_B

BUT - as you can see - right before checking max_file_size variable - PHP performs EXACTLY THE SAME CHECK for upload_max_filesize variable!!! So - there we have it.

Conclusion: IMHO - op is right - there is 0 point in including MAX_FILE_SIZE into your forms! Simply set upload_max_filesize in your php.ini file or dynamically via ini_set().

At the moment there are no browsers that actually care about the MAX_FILE_SIZE directive so it is pretty pointless. I suppose it does give you more granular control over max sizes on upload (as the poster above stated) rather than going with php.ini's, but personally I just ignore it, and you probably should too. It will certainly not stop a user uploading a larger than required file - the manual is fairly misleading in this regard.

Until we find browsers that support it, there's no point on the client side.

However, on the server side, MAX_FILE_SIZE does affect the values you get from $_FILES['your_file'] .

Assuming the browser's request actually made it through post_max_size , usually this is what PHP gives:

array(5) {
    ["name"]=> string(11) "my_upload.dll"
    ["type"]=> string(24) "application/x-msdownload"
    ["tmp_name"]=> string(26) "C:\WINDOWS\Temp\php86A.tmp"
    ["error"]=> int(0) // UPLOAD_ERR_OK
    ["size"]=> int(238592)
}

But if uploaded file size exceeds MAX_FILE_SIZE , you'd see:

array(5) {
    ["name"]=> string(11) "my_upload.dll"
    ["type"]=> string(0) ""
    ["tmp_name"]=> string(0) ""
    ["error"]=> int(2) // UPLOAD_ERR_FORM_SIZE
    ["size"]=> int(0)
} 

And the part on " MAX_FILE_SIZE must precede the file input field" is not a joke. It actually works because PHP will interpret the browser's POST request payload sequentially:

<input name=F1 type=file> 
<input name=F2 type=file>
F1 and F2 will not be affected by MAX_FILE_SIZE

<input name=MAX_FILE_SIZE value=1024 type=hidden>
<input name=F3 type=file>
<input name=F4 type=file>
F3 and F4 will have MAX_FILE_SIZE = 1024 bytes

<input name=MAX_FILE_SIZE value=0 type=hidden>
<input name=F5 type=file>
<input name=F6 type=file>
F5 and F6 will have MAX_FILE_SIZE = 0 (infinite)

<input name=MAX_FILE_SIZE value=1 type=hidden>
<input name=F7 type=file> 
<input name=F8 type=file>
F7 and F8 will have MAX_FILE_SIZE = 1 byte

Also note that PHP interprets MAX_FILE_SIZE case insensitively, so maX_fILe_sIZE and Max_File_SIZE would work too.

I believe the point is that conformant browsers would prevent form submission in the case where the user selected a file that was too large, which would save them having to perform at least a partial upload (which could take a while) of a file that was going to be rejected.

On the server side, PHP still checks and enforces the various limits set in PHP.ini, and will reference the fact that an upload was too large in the normal manner, ie an error code set in $_FILES. You might think of the field as an analogy to JavaScript validation - we might do a quick client-side check for the user's convenience, but we still do a proper server-side test and enforce it for all requests.

As others have stated, there don't appear to be any browsers that actually bother to perform this check, making it relatively useless.

What follows is me being wrong, please read the other answers which are better-informed, and accurate (AFAIK).

I think the point is exactly as it states:

This form element should always be used as it saves users the trouble of waiting for a big file being transferred only to find that it was too large and the transfer failed

Yes, it can be fooled, and so shouldn't be relied on to prevent larger files from being uploaded, but for non-malicious users if the uploaded file is bigger than the integer in this field, PHP disallows this upload and presents an error code in the $_FILES array (source - comments on php.net ).

I use it to set file size limit when a particular application needs smaller files than the limit in php.ini . My php scripts check it, but it is set in the HTML form. Different forms have different file size limits. I am not sure if this has much to do with the intended use, but it makes it easier to reuse my scripts. It would be good if it could be checked at the browser level, but it's not the only reason it is useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM