Upload of too large files fail silently

I’m messing with the file upload capability, but am having problems with uploading large files whereby files that are too large (which I’ll define below) are failing with no indication; Yii just displays a blank create form again.

Here’s my environment:

  • I have a validator rule set (arbitrarily) defining maxSize as 1MB

  • main index.php has YII_DEBUG defined, and PHP.INI has display_errors=on & error_reporting=E_ALL | E_STRICT

  • Running XAMPP with PHP 5.3.8 & Yii 1.1.10

  • PHP.INI has post_max_size = 8M

Files < 1MB upload OK. Yii correctly reports an error if the file >1MB but < 8MB. The problems occur for files > 8MB - the only indication I have of failure is a message in the PHP Log:


PHP Warning:  POST Content-Length of 9968457 bytes exceeds the limit of 8388608 bytes in Unknown on line 0

I could obviously change the limits here, but the troubling part is that when they’re exceeded, the app fails silently. What do I have to change in order to catch / report the problem?

for uploading there are many setting you should do :




max_execution_time = 0 //if file is  too large  the time will exhaust  ; default is 30 s;


upload_max_filesize = 8M


post_max_size = 20M  


//the post size should be greater then the file upload size ; and may be i miss some config .just a tip



:lol:

Yes I know all that and I did say in my post I could change the limits. That’s not the issue I was was asking. Since “unlimited” is not an option there will always be a point at which the upload will fail. When that is reached I don’t want it to be silent as is happening at the moment. There has to be an indication to the user. How do I achieve that?

If you set the maxSize attribute of the CFileValidator then you should get the error message displayed… could be you forgot to call the error() method as this is the one that specify where will the error be displayed?

I do get the error message if the maxSize < file size < max_post_size. In that scenario everything works fine. But in the scenario where maxSize < max_post_size < file size, then it fails silently. Nothing else changed.

Tbh I think I’ll just put in a decent uploader that can work round post size etc. and handle any size file. Just a little worrying when this sort of stuff happens - I like to see notifications.

I had exactly the same problem as yours. "post_max_size" and "upload_max_filesize" in the php.ini solved the problem. Initially I configured the "upload_max_filesize" and forgot about "post_max_size" which was 2M xD So make you sure you change that value!

Even if you set the post_max_size to some large value there is a possibility that user will upload even bigger file. Also not any hosting allows to change post_max_size.

There is a possibility to check whether too large file was uploaded and display error:




class XUtils {

    /**

	 * Returns max post size from "php.ini"

	 * @return integer max_post_size

	 */

    public static function post_max_size() {

        return self::return_bytes(ini_get('post_max_size'));

    }


    /**

	 * Test request to big file (more post_max_size)

	 * @return bool has big file or no

	 */

    public static function hasBigFile() {

        if (isset($_SERVER['CONTENT_TYPE'])) {

            $hasContent = preg_match("/^multipart\/form-data; boundary=/",$_SERVER['CONTENT_TYPE']);

            $hasContent = $hasContent && isset($_SERVER['CONTENT_LENGTH']) && (

                $_SERVER['CONTENT_LENGTH'] > self::post_max_size()

            );

            return $hasContent;

        } else {

            return false;

        }

    }

}



Now you can call XUtils::hasBigFile() and raise exception or display validation error.

@mdomba Maybe such check should be in the yii’s CFileValidator?

You deserve a medal for this post. This should definitely make it into the core, as file uploading is an incredibly frustrating experience.

Your return_bytes was not posted, so I used the following functions to return bytes from human readable signifiers:

public static function return_bytes($str) {

    &#036;bytes = 0;





    &#036;bytes_array = array(


        'B' =&gt; 1,


        'KB' =&gt; 1024,


        'MB' =&gt; 1024 * 1024,


        'M' =&gt; 1024 * 1024,


        'GB' =&gt; 1024 * 1024 * 1024,


        'TB' =&gt; 1024 * 1024 * 1024 * 1024,


        'PB' =&gt; 1024 * 1024 * 1024 * 1024 * 1024,


    );





    &#036;bytes = floatval(&#036;str);





    if (preg_match('#([KMGTP]?B|[M])&#036;#si', &#036;str, &#036;matches) &amp;&amp; &#33;empty(&#036;bytes_array[&#036;matches[1]])) {


        &#036;bytes *= &#036;bytes_array[&#036;matches[1]];


    }








    &#036;bytes = intval(round(&#036;bytes, 2));





    return &#036;bytes;


}

Just come back to this - glad to see someone figure out a solution - thanks!

Fwiw I overrode the run action of my controller to enable this application wide, then returned http code 413:




    public function run($actionID)

    {


        if (isset($_SERVER['CONTENT_TYPE'])

            &&

            preg_match("/^multipart\/form-data; boundary=/",$_SERVER['CONTENT_TYPE'])

            && 

            isset($_SERVER['CONTENT_LENGTH']) 

            && 

            $_SERVER['CONTENT_LENGTH'] > ini_get('post_max_size')

           )

        { 

            throw new CHttpException(413,'Request Entity Too Large.');

        }

        parent::run($actionID);

    }