Intereting Posts

PHP получает фактический максимальный размер загрузки

Когда используешь

ini_get("upload_max_filesize"); 

он фактически дает вам строку, указанную в файле php.ini.

Неправильно использовать это значение в качестве ссылки для максимального размера загрузки, поскольку

  • можно использовать так называемые сокращенные байты, такие как 1M и т. д., в которых требуется много дополнительного синтаксического анализа
  • когда upload_max_filesize, например, 0.25M , на самом деле это ZERO, что делает синтаксический анализ значения намного сложнее снова
  • также, если значение содержит любые пробелы, например, как ZERO по php, тогда как при использовании ini_get значение без пробелов

Итак, есть ли способ получить значение, фактически используемое PHP, помимо сообщения, ini_get , или что это лучший способ его определить?

У Drupal это реализовано довольно элегантно:

 // Returns a file size limit in bytes based on the PHP upload_max_filesize // and post_max_size function file_upload_max_size() { static $max_size = -1; if ($max_size < 0) { // Start with post_max_size. $post_max_size = parse_size(ini_get('post_max_size')); if ($post_max_size > 0) { $max_size = $post_max_size; } // If upload_max_size is less, then reduce. Except if upload_max_size is // zero, which indicates no limit. $upload_max = parse_size(ini_get('upload_max_filesize')); if ($upload_max > 0 && $upload_max < $max_size) { $max_size = $upload_max; } } return $max_size; } function parse_size($size) { $unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size. $size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size. if ($unit) { // Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by. return round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))); } else { return round($size); } } 

Вышеупомянутые функции доступны в любом месте Drupal, или вы можете скопировать его и использовать в своем собственном проекте в соответствии с условиями лицензии GPL версии 2 или более поздней.

Что касается частей 2 и 3 вашего вопроса, вам нужно будет вручную проанализировать файл php.ini . Это, по сути, ошибки конфигурации, и PHP прибегает к восстановлению поведения. Кажется, вы действительно можете получить местоположение загруженного файла php.ini на PHP, хотя попытка чтения с него может не работать с включенным или безопасным режимом:

 $max_size = -1; $files = array_merge(array(php_ini_loaded_file()), explode(",\n", php_ini_scanned_files())); foreach (array_filter($files) as $file) { $ini = parse_ini_file($file); $regex = '/^([0-9]+)([bkmgtpezy])$/i'; if (!empty($ini['post_max_size']) && preg_match($regex, $ini['post_max_size'], $match)) { $post_max_size = round($match[1] * pow(1024, stripos('bkmgtpezy', strtolower($match[2]))); if ($post_max_size > 0) { $max_size = $post_max_size; } } if (!empty($ini['upload_max_filesize']) && preg_match($regex, $ini['upload_max_filesize'], $match)) { $upload_max_filesize = round($match[1] * pow(1024, stripos('bkmgtpezy', strtolower($match[2]))); if ($upload_max_filesize > 0 && ($max_size <= 0 || $max_size > $upload_max_filesize) { $max_size = $upload_max_filesize; } } } echo $max_size; 

Вот полное решение. Он берет на себя все ловушки, такие как сокращенное байтовое обозначение, а также считает post_max_size:

 /** * This function transforms the php.ini notation for numbers (like '2M') to an integer (2*1024*1024 in this case) * * @param string $sSize * @return integer The value in bytes */ function convertPHPSizeToBytes($sSize) { // $sSuffix = strtoupper(substr($sSize, -1)); if (!in_array($sSuffix,array('P','T','G','M','K'))){ return (int)$sSize; } $iValue = substr($sSize, 0, -1); switch ($sSuffix) { case 'P': $iValue *= 1024; // Fallthrough intended case 'T': $iValue *= 1024; // Fallthrough intended case 'G': $iValue *= 1024; // Fallthrough intended case 'M': $iValue *= 1024; // Fallthrough intended case 'K': $iValue *= 1024; break; } return (int)$iValue; } function getMaximumFileUploadSize() { return min(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize'))); } 

Это безошибочная версия этого источника: http://www.smokycogs.com/blog/finding-the-maximum-file-upload-size-in-php/ .

Это то, что я использую:

 function asBytes($ini_v) { $ini_v = trim($ini_v); $s = [ 'g'=> 1<<30, 'm' => 1<<20, 'k' => 1<<10 ]; return intval($ini_v) * ($s[strtolower(substr($ini_v,-1))] ?: 1); } 

Похоже, это невозможно.

Из-за этого я буду продолжать использовать этот код:

 function convertBytes( $value ) { if ( is_numeric( $value ) ) { return $value; } else { $value_length = strlen($value); $qty = substr( $value, 0, $value_length - 1 ); $unit = strtolower( substr( $value, $value_length - 1 ) ); switch ( $unit ) { case 'k': $qty *= 1024; break; case 'm': $qty *= 1048576; break; case 'g': $qty *= 1073741824; break; } return $qty; } } $maxFileSize = convertBytes(ini_get('upload_max_filesize')); 

Первоначально из этого полезного комментария php.net.

ЕЩЕ ОТКРЫТЬ ДЛЯ ПРИНЯТИЯ ЛУЧШИХ ОТВЕТОВ

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

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

Ну, вы всегда можете использовать этот синтаксис, который даст вам правильные номера из файла PHP ini:

 $maxUpload = (int)(ini_get('upload_max_filesize')); $maxPost = (int)(ini_get('post_max_size')); 

рынок