如何正常处理超过PHP的`post_max_size`的文件?

我正在处理一个将文件附加到电子邮件的PHP表单,并试图正确处理上传文件太大的情况。

我了解到, php.ini中有两个设置会影响file upload的最大大小: upload_max_filesizepost_max_size

如果一个文件的大小超过了upload_max-filesize ,那么PHP将文件的大小作为0返回。 我可以检查。

但是,如果它超过了post_max_size ,我的脚本就会失败并返回空白表单。

有什么办法来捕捉这个错误?

http://ca2.php.net/manual/en/ini.core.php#ini.post-max-size

如果发布数据的大小大于post_max_size,则$ _POST和$ _FILES超全局variables是空的 。 这可以通过各种方式进行跟踪,例如将$ _GETvariables传递给处理数据的脚本,然后检查是否设置了$ _GET ['processed']。

所以不幸的是,它看起来不像PHP发送错误。 而且由于它发送的是空的$ _POST数组,这就是为什么你的脚本回到空白表单 – 它不认为它是一个POST。 (很不好的devise决定恕我直言)

这位评论者也有一个有趣的想法。

看来post_max_size和$ _SERVER ['CONTENT_LENGTH']之间比较优雅的方式。 请注意,后者不仅包括上传的文件的大小加上发布数据,还包括多部分序列。

有一种方法可以捕捉/处理超过最大文件大小的文件,这是我的首选,因为它告诉最终用户发生了什么事以及谁是错误的;)

  if(empty($_FILES) && empty($_POST) && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){ //catch file overload error... $postMax = ini_get('post_max_size'); //grab the size limits... echo "<p style=\"color: #F00;\">\nPlease note files larger than {$postMax} will result in this error!<br>Please be advised this is not a limitation in the CMS, This is a limitation of the hosting server.<br>For various reasons they limit the max size of uploaded files, if you have access to the php ini file you can fix this by changing the post_max_size setting.<br> If you can't then please ask your host to increase the size limits, or use the FTP uploaded form</p>"; // echo out error and solutions... addForm(); //bounce back to the just filled out form. } elseif(// continue on with processing of the page... 

我们遇到了SOAP请求的问题,因为检查$ _POST和$ _FILES的空白不起作用,因为它们在有效的请求中也是空的。

因此我们实施了一个检查,比较CONTENT_LENGTH和post_max_size。 抛出的exception后来被我们注册的exception处理程序转换成XML-SOAP-FAULT。

 private function checkPostSizeExceeded() { $maxPostSize = $this->iniGetBytes('post_max_size'); if ($_SERVER['CONTENT_LENGTH'] > $maxPostSize) { throw new Exception( sprintf('Max post size exceeded! Got %s bytes, but limit is %s bytes.', $_SERVER['CONTENT_LENGTH'], $maxPostSize ) ); } } private function iniGetBytes($val) { $val = trim(ini_get($val)); if ($val != '') { $last = strtolower( $val{strlen($val) - 1} ); } else { $last = ''; } switch ($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': $val *= 1024; // fall through case 'm': $val *= 1024; // fall through case 'k': $val *= 1024; // fall through } return $val; } 

build立在@Matt McCormick和@ AbdullahAJM的答案上,这是一个PHPtesting用例,它检查testing中使用的variables是否被设置,然后检查$ _SERVER ['CONTENT_LENGTH']是否超过了php_max_filesize设置:

  if ( isset( $_SERVER['REQUEST_METHOD'] ) && ($_SERVER['REQUEST_METHOD'] === 'POST' ) && isset( $_SERVER['CONTENT_LENGTH'] ) && ( empty( $_POST ) ) ) { $max_post_size = ini_get('post_max_size'); $content_length = $_SERVER['CONTENT_LENGTH'] / 1024 / 1024; if ($content_length > $max_post_size ) { print "<div class='updated fade'>" . sprintf( __('It appears you tried to upload %d MiB of data but the PHP post_max_size is %d MiB.', 'csa-slplus'), $content_length, $max_post_size ) . '<br/>' . __( 'Try increasing the post_max_size setting in your php.ini file.' , 'csa-slplus' ) . '</div>'; } } 

这是一个简单的方法来解决这个问题:

只需在代码开始处调用“checkPostSizeExceeded”即可

 function checkPostSizeExceeded() { if (isset($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'POST' and isset($_SERVER['CONTENT_LENGTH']) and empty($_POST)//if is a post request and $_POST variable is empty(a symptom of "post max size error") ) { $max = get_ini_bytes('post_max_size');//get the limit of post size $send = $_SERVER['CONTENT_LENGTH'];//get the sent post size if($max < $_SERVER['CONTENT_LENGTH'])//compare throw new Exception( 'Max size exceeded! Were sent ' . number_format($send/(1024*1024), 2) . 'MB, but ' . number_format($max/(1024*1024), 2) . 'MB is the application limit.' ); } } 

请记住复制这个辅助function:

 function get_ini_bytes($attr){ $attr_value = trim(ini_get($attr)); if ($attr_value != '') { $type_byte = strtolower( $attr_value{strlen($attr_value) - 1} ); } else return $attr_value; switch ($type_byte) { case 'g': $attr_value *= 1024*1024*1024; break; case 'm': $attr_value *= 1024*1024; break; case 'k': $attr_value *= 1024; break; } return $attr_value; }