PHP获取实际的最大上传大小 [英] PHP get actual maximum upload size
问题描述
使用时
ini_get("upload_max_filesize");
它实际上为您提供了php.ini文件中指定的字符串.
将此值用作最大上传大小的参考不是很好,因为
- 可以使用所谓的 shorthandbytes 像
1M
一样,需要大量其他解析 - 例如当upload_max_filesize为
0.25M
时,实际上为零,使得再次解析值变得更加困难 - 此外,如果该值包含空格,例如被php解释为零,则使用
ini_get
时该值显示不带空格的值
那么,除了ini_get
报告的方法之外,还有什么方法可以获取PHP实际使用的值,或者确定它的最佳方法是什么?
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中获得加载的php.ini
文件的位置,尽管尝试从中读取文件可能无法在启用basedir或安全模式的情况下起作用:
$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;
When using
ini_get("upload_max_filesize");
it actually gives you the string specified in the php.ini file.
It is not good to use this value as a reference for the maximum upload size because
- it is possible to use so-called shorthandbytes like
1M
and so on which needs alot of additional parsing - when upload_max_filesize is for example
0.25M
, it actually is ZERO, making the parsing of the value much harder once again - also, if the value contains any spaces like it is interpreted as ZERO by php, while it shows the value without spaces when using
ini_get
So, is there any way to get the value actually being used by PHP, besides the one reported by ini_get
, or what is the best way to determinate it?
Drupal has this implemented fairly elegantly:
// 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);
}
}
The above functions are available anywhere in Drupal, or you can copy it and use it in your own project subject to the terms of the GPL license version 2 or later.
As for parts 2 and 3 of your question, you will need to parse the php.ini
file directly. These are essentially configuration errors, and PHP is resorting to fallback behaviors. It appears you can actually get the location of the loaded php.ini
file in PHP, although trying to read from it may not work with basedir or safe-mode enabled:
$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;
这篇关于PHP获取实际的最大上传大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!