9

This is my upload form:

<form action="uploads.php" method="post" enctype="multipart/form-data">
    <input name="fileupload" type="file" multiple>
    <button>Upload</button>
</form>

My max upload sizes are set like this:

; Maximum allowed size for uploaded files.
upload_max_filesize = 5M

; Must be greater than or equal to upload_max_filesize
post_max_size = 5M

If I upload a file that is larger then 5M var_dump($_FILES) is empty. I can do that:

if($_FILES){
    echo "Upload done!";
}

$_FILES is not set if the file is larger then 5M. But this is a bit strange. How would you do that?

EDIT:

var_dump of file over 5M:

array(0) {
}

var_dump of file <= 5M:

array(1) {
  ["fileupload"]=>
  array(5) {
    ["name"]=>
    string(13) "netzerk12.pdf"
    ["type"]=>
    string(15) "application/pdf"
    ["tmp_name"]=>
    string(22) "/tmp/uploads/phpWhm8M0"
    ["error"]=>
    int(0)
    ["size"]=>
    int(352361)
  }
}
tuna
  • 931
  • 2
  • 10
  • 28
  • Are you sure that it's empty? Can you show us the actual `var_dump()` output? – Austin Brunkhorst Sep 02 '13 at 07:37
  • yes, you will get it empty. you have to set upload_max_filesize and post_max_size variable in ini. – Hasina Sep 02 '13 at 07:38
  • 1
    Set `post_max_size` > `upload_max_filesize` and you should get your error message (i think) – Rob Sep 02 '13 at 07:44
  • 1
    Like @Rob said, `UPLOAD_ERR_INI_SIZE` error should be thrown. http://www.php.net/manual/en/features.file-upload.errors.php – Glavić Sep 02 '13 at 07:45
  • @Glavić this is a good point but didn't helps either. Like I said $_FILES is not set at that point. $_FILES['fileupload']['error'] is not present. – tuna Sep 02 '13 at 07:50
  • @methanol I have just tested this on my localhost, and it works. `$_FILES['fileupload']['error']` returns `int(1)` which is `UPLOAD_ERR_INI_SIZE`. Have you set `post_max_size > upload_max_filesize` ? – Glavić Sep 02 '13 at 07:57

4 Answers4

12

You could check the $_SERVER['CONTENT_LENGTH']:

// check that post_max_size has not been reached
// convert_to_bytes is the function turn `5M` to bytes because $_SERVER['CONTENT_LENGTH'] is in bytes.
if (isset($_SERVER['CONTENT_LENGTH']) 
    && (int) $_SERVER['CONTENT_LENGTH'] > convert_to_bytes(ini_get('post_max_size'))) 
{
  // ... with your logic
  throw new Exception('File too large!');
}
xdazz
  • 158,678
  • 38
  • 247
  • 274
  • This works for me but I think you can still upload large files and "flood" the server – tuna Sep 02 '13 at 07:55
  • Great answer, you'll probably want to replace `convert_to_bytes(ini_get('post_max_size')` with whatever makes sense for the situation. `$_SERVER['CONTENT_LENGTH']` returns bytes. – Goose May 15 '17 at 17:56
  • @Goose but `post_max_size` is string, eg 128M – zanderwar Mar 30 '20 at 12:18
  • @zanderwar Yep, it's just a dummy function which expect to convert string like "128M" to bytes. – xdazz Mar 31 '20 at 04:22
6

Like Rob mentioned, your post_max_size should be greater than your upload_max_filesize.

After that you can check $_FILES['fileupload']['error'] if it is UPLOAD_ERR_INI_SIZE the uploaded file is to large.

So in your php.ini set

; Maximum allowed size for uploaded files.
upload_max_filesize = 5M

; Must be greater than or equal to upload_max_filesize
post_max_size = 10M

In your uploads.php check

if($_FILES['fileupload']['error'] === UPLOAD_ERR_INI_SIZE) {
    // Handle the error
    echo 'Your file is too large.';
    die();
}
// check for the other possible errors 
// http://php.net/manual/features.file-upload.errors.php
Community
  • 1
  • 1
Florian Grell
  • 995
  • 7
  • 18
  • So I have to set post_max_size to 9petabytes? If I set is to 100M for example then people start to upload 101M files and this doesn't work anymore. Yes I reconstructed it. upload_max_filesize = 5M post_max_size = 6M. If I upload 6.4M file $_FILES remains empty. – tuna Sep 02 '13 at 08:08
  • If you want to allow unlimited uploads, yes. But I would set it to a sane number. And if your `$_FILES` array is empty, than the file was to large. You can check for `$_FILES['fileupload']['error'] === UPLOAD_ERR_NO_FILE` to check if there was no file uploaded at all. – Florian Grell Sep 02 '13 at 11:03
2

I had the same problem, where $_FILES would be empty if the uploaded file is too large. Based on the solutions of xdazz and Florian, I concluded that:

  • If the file size is greater than post_max_size, then $_FILES is empty and $_FILES['fileupload']['error'] is therefore not defined: use the solution of xdazz. However, you get a warning message from PHP (Warning: POST Content-Length of xxx bytes exceeds the limit of yyy bytes in Unknown on line 0).
  • If the file size is between post_max_size and upload_max_filesize, in that case you can use $_FILES['fileupload']['error'], without having to be bothered with PHP warning messages.

In short use the following code:

    if (isset($_SERVER['CONTENT_LENGTH']) &&
        (int) $_SERVER['CONTENT_LENGTH'] > (1024*1024*(int) ini_get('post_max_size'))) 
    {
        // Code to be executed if the uploaded file has size > post_max_size
        // Will issue a PHP warning message 
    }

    if ($_FILES[$this->name]['error'] === UPLOAD_ERR_INI_SIZE) {
        // Code to be executed if the uploaded file has size between upload_max_filesize and post_max_size
        // Will not issue any PHP warning message
    }
Community
  • 1
  • 1
Daniel
  • 202
  • 2
  • 7
-1

You should set the max allowed file size more than 5M, then with PHP check if the file size exceed 5M. Make sure your webserver post body size is updated with the new size as well.

Limiting file size based on php ini is not the best solution, because it will limit you. What if you want to check another file not exceed 3MB in another script?

 if ($_FILES['fileupload']['size'] > 5242880) // 5242880 = 5MB
      echo 'your file is too large';
alex smith
  • 470
  • 6
  • 16
  • `$_FILES` will return empty – Bora Sep 02 '13 at 07:45
  • 3
    While this may work, I don't recommend it. It's a waste of bandwidth to allow users to upload large files that you will just throw away. – Rob Sep 02 '13 at 07:45