yii: Yii incorrectly handles oversized file uploads

When submitting large files, changed settings in php.ini, should include not only upload_max_filesize, but also post_max_size. Many developers forgets about second parameter (as this is mentioned in PHP File Uploads Common Pitfalls). When this happens (developer forgets to rise post_max_size and it is set to default value of 8M) file upload through standard PHP / Yii form (<input type="file"> field) will fail.

Citing post_max_size variable doc:

If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty.

Yii seems to be handling this situation incorrectly.

I’ve had upload_max_filesize set to 1G, but post_max_size remaining on default 8M. When trying to upload file larger than 55MB (see here) I faced a strage Yii application behavior.

When CHttpRequest->enableCsrfValidation is set to true Yii application failed with 400: CSRF token could not be verified. When this option was disabled (default), Yii was redirecting page back to the same form (not to list of files, as in the code, probably due to broken request), but without displaying any error.

Increasing post_max_size to 1G and restarting server fixed the problem. I’m now able to upload files with 130MB+ in size with and without CSRF validation enabled.

About this issue

  • Original URL
  • State: closed
  • Created 11 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

This one can’t be fixed. As already been told here, in case PHP ‘post max size’ limit is overflowed, the $_POST array is not filled up. This is something Yii simply can’t handle.

Yii application failed with 400: CSRF token could not be verified

Broken request – no source for CSRF.

When this option was disabled (default), Yii was redirecting page back to the same form (not to list of files, as in the code, probably due to broken request), but without displaying any error.

This happens cause of lines like following inside the controller:

$model = new MyForm();
if (isset($_POST[‘MyForm’])) { // No POST -> check failed
    $model->attributes = $_POST[‘MyForm’];
    if ($model->validate()) {…} // never reached -> no error is shown
}

The only way developer can avoid this situation is creating some ‘requirements check’ script, which should checks all PHP ini settings and server configuration. In Yii2 there is method ‘YiiRequirementChecker::checkUploadMaxFileSize()’, which handles such situation properly. You may try to use ‘YiiRequirementChecker’ as basis for ‘requirements check’ script for Yii1 as well.

@trejder when you’re exceeding post_max_size it’s like submitting a page w/o any data and it behaves according to it. This is default PHP behavior as well.

Since this is really a big trouble when you’re trying to debug it I think we could do something like the following in file validator:

if(Yii::app()->request->isPostRequest && empty($_FILES) && empty($_POST))
{
        throw new CException('Unable to upload file. Please check your post_max_size in php.ini. Current value is: '.ini_get('post_max_size'));
}