Как изящно обрабатывать файлы, которые превышают PHP `post_max_size`?
Я работаю над формой PHP, которая прикрепляет файл к электронному письму, и пытаюсь корректно обрабатывать случаи, когда загружаемый файл слишком велик.
Я узнал, что в php.ini
есть две настройки, которые влияют на максимальный размер загружаемого файла: upload_max_filesize
и post_max_size
.
Если размер файла превышает upload_max_filesize
, PHP возвращает размер файла как 0. Это хорошо; Я могу проверить это.
Но если он превышает post_max_size
, мой сценарий завершается сбоем и возвращается к чистому виду.
Есть ли способ отловить эту ошибку?
Ответы
Ответ 1
Из документации :
Если размер почтовых данных больше чем post_max_size, то $ _POST и Суперглобальные переменные $ _FILES пусты. Этот можно отслеживать различными способами, например, передав переменную $ _GET скрипт обрабатывает данные, то есть форму action = "edit.php? processing = 1"> и затем проверка, если $ _GET ['обработано'] является набор.
Так что, к сожалению, это не похоже на то, что PHP отправляет ошибку. И поскольку он посылает пустой массив $ _POST, именно поэтому ваш скрипт возвращается к чистому виду - он не думает, что это POST. (Довольно неудачное дизайнерское решение ИМХО)
Этот комментатор также имеет интересную идею.
Кажется, что более элегантный способ сравнение между post_max_size и $ _SERVER [ 'CONTENT_LENGTH']. пожалуйста Отметим, что последний включает в себя не только размер загружаемого файла плюс данные поста но также составные последовательности.
Ответ 2
есть способ ловить/обрабатывать файлы, превышающие максимальный размер сообщения, это мое предпочтение, так как оно сообщает конечному пользователю, что произошло и кто виноват;)
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.
}
else {
// continue on with processing of the page...
}
Ответ 3
У нас возникла проблема с запросами SOAP, когда проверка на пустоту $_POST и $_FILES не работает, потому что они также пусты в действительных запросах.
Поэтому мы внедрили проверку, сравнив CONTENT_LENGTH и post_max_size. Выброшенное исключение позже преобразуется в 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;
}
Ответ 4
Основываясь на ответах @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>';
}
}
Ответ 5
Это простой способ решить эту проблему:
Просто запустите "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;
}