PHP 获取实际的最大上传大小

php
2022-08-30 09:20:47

使用时

ini_get("upload_max_filesize");

它实际上为您提供了php.ini文件中指定的字符串。

使用此值作为最大上载大小的参考是不好的,因为

  • 可以使用所谓的速记字节,例如需要大量额外解析的快捷字节等1M
  • 例如,当upload_max_filesize为零时,它实际上是零,这使得值的解析再次变得更加困难。0.25M
  • 此外,如果值包含任何空格,则 php 将其解释为零,而在使用时,它显示的值不带空格ini_get

那么,除了 报告的值之外,还有没有办法获得 PHP 实际使用的值,或者确定它的最佳方法是什么?ini_get


答案 1

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正在诉诸回退行为。看起来您实际上可以在PHP中获取加载文件的位置,尽管尝试从中读取可能无法在启用baseir或安全模式的情况下工作:php.iniphp.ini

$max_size = -1;
$post_overhead = 1024; // POST data contains more than just the file upload; see comment from @jlh
$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 - $post_overhead;
    }
  }
  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;

答案 2

这是完整的解决方案。它处理所有陷阱,如速记字节表示法,并考虑post_max_size:

/**
* This function returns the maximum files size that can be uploaded 
* in PHP
* @returns int File size in bytes
**/
function getMaximumFileUploadSize()  
{  
    return min(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize')));  
}  

/**
* 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;
}      

推荐