Как изящно обрабатывать файлы, которые превышают PHP `post_max_size`?

Я работаю над формой PHP, которая прикрепляет файл к электронной почте и пытается изящно обрабатывать случаи, когда загруженный файл слишком велик.

Я узнал, что в php.ini есть два параметра, которые влияют на максимальный размер загрузки файла: upload_max_filesize и post_max_size .

Если размер файла превышает upload_max-filesize , PHP возвращает размер файла как 0. Это нормально; Я могу проверить это.

Но если он превышает post_max_size , мой скрипт терпит неудачу и возвращается к пустой форме.

Есть ли способ уловить эту ошибку?

Из документации :

Если размер пост-данных больше, чем post_max_size, суперглавы $ _POST и $ _FILES пустые . Это можно отслеживать различными способами, например, передавая переменную $ _GET скрипту, обрабатывающему данные, т. Е. <Form action = "edit.php? Обработан = 1">, а затем проверяет, является ли $ _GET ['обработанным "] задавать.

К сожалению, это не похоже на то, что PHP отправляет ошибку. И поскольку он отправляет пустой массив $ _POST, вот почему ваш скрипт возвращается к пустой форме – он не считает, что это POST. (Довольно плохое дизайнерское решение IMHO)

У этого комментатора также есть интересная идея.

Кажется, что более элегантным способом является сравнение между 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 позже преобразуется в 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; } 

Основываясь на ответах @Matt McCormick и @ AbdullahAJM, здесь представлен тестовый пример PHP, который проверяет переменные, используемые в тесте, и затем проверяет, превышает ли значение $ _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 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; }