Is there any way to get the byte values from the strings returned from functions like ini_get('upload_开发者_StackOverflow中文版max_filesize')
and ini_get('post_max_size')
when they are using shorthand byte notation? For example get 4194304 from 4M ? I could hack together a function that does this but I would be surprised if there wasn't some built in way of doing this.
The paragraph you linked to ends:
You may not use these shorthand notations outside of php.ini, instead use an integer value of bytes. See the ini_get() documentation for an example on how to convert these values.
This leads you to something like this (which I have slightly modified):
function return_bytes($val)
{
$val = trim($val);
if (is_numeric($val))
return $val;
$last = strtolower($val[strlen($val)-1]);
$val = substr($val, 0, -1); // necessary since PHP 7.1; otherwise optional
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
Use it like so:
echo return_bytes("3M");
// Output: 3145728
There is no built-in function to perform this task; recall that, really, INI settings are designed for use internally within PHP. The PHP source uses a similar function to the above.
Gah! Just found the answer on http://www.php.net/manual/en/function.ini-get.php
Just needed to RTM...
function return_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
This is my suggestion which should be future-proof (with regard to PHP Versions 7++)!
function return_bytes($val, $gotISO = false) {
// This is my ultimate "return_bytes" function!
// Converts (not only) the PHP shorthand notation which is returned by e.g. "ini_get()"
// Special features:
// Doesn't need regular expression and switch-case conditionals.
// Identifies beside "Kilo", "Mega" and "Giga" also "Tera", "Peta", "Exa", "Zetta", and "Yotta" too!
// Ignores spaces and doesn't make no difference between e.g. "M" or "MB"!
// By default possible commas (,) as thousand separator will be erased. Example: "1,000.00" will "be 1000.00".
// If ($gotISO == true) it converts ISO formatted values like "1.000,00" into "1000.00".
$pwr = 0;
if(empty($val)) return 0;
$val = trim($val);
if (is_numeric($val)) return $val;
if ($gotISO) {
$val = str_replace('.','',$val); // wipe possibe thousend separators (.)
$val = str_replace(',','.',$val); // convert ISO comma to value point
} else {
$val = str_replace(',','',$val); // wipe possibe thousend separators (,)
}
$val = str_replace(' ','',$val);
if (floatval($val) == 0) return 0;
if (stripos($val, 'k') !== false) $pwr = 1;
elseif (stripos($val, 'm') !== false) $pwr = 2;
elseif (stripos($val, 'g') !== false) $pwr = 3;
elseif (stripos($val, 't') !== false) $pwr = 4;
elseif (stripos($val, 'p') !== false) $pwr = 5;
elseif (stripos($val, 'e') !== false) $pwr = 6;
elseif (stripos($val, 'z') !== false) $pwr = 7;
elseif (stripos($val, 'y') !== false) $pwr = 8;
$val *= pow(1024, $pwr);
return $val;
}
... have fun with it!
I found a lot of solution to solve this problem and there should have been a builtin function to solve this. In any case two things to highlight about this problem:
- This is very specific to PHP's shorthand byte values as explained here: http://php.net/manual/en/faq.using.php#faq.using.shorthandbytes and should only be used in this context.
- Most modern IDEs will give warning for
switch
statements withoutbreak
.
Here is a solution that covers everything:
/**
* Convert PHP's directive values to bytes (including the shorthand syntax).
*
* @param string $directive The PHP directive from which to get the value from.
*
* @return false|int Returns the value of the directive in bytes if available, otherwise false.
*/
function php_directive_value_to_bytes($directive) {
$value = ini_get($directive);
// Value must be a string.
if (!is_string($value)) {
return false;
}
preg_match('/^(?<value>\d+)(?<option>[K|M|G]*)$/i', $value, $matches);
$value = (int) $matches['value'];
$option = strtoupper($matches['option']);
if ($option) {
if ($option === 'K') {
$value *= 1024;
} elseif ($option === 'M') {
$value *= 1024 * 1024;
} elseif ($option === 'G') {
$value *= 1024 * 1024 * 1024;
}
}
return $value;
}
Neither one of the Version shown above will work with PHP 7.2x anymore, as I found out.By use of this,with PHP 7.0 + 7.1, it works, but not with PHP 7.x Ernie
private function return_bytes ($val) {
if(empty($val))return 0;
$val = trim($val);
preg_match('#([0-9]+)[\s]*([a-z]+)#i', $val, $matches);
$last = '';
if(isset($matches[2])){
$last = $matches[2];
}
if(isset($matches[1])){
$val = (int) $matches[1];
}
switch (strtolower($last)){
case 'g':
case 'gb':
$val *= 1024;
case 'm':
case 'mb':
$val *= 1024;
case 'k':
case 'kb':
$val *= 1024;
}
return (int) $val;
}
Here is one way.
$str=ini_get('upload_max_filesize');
preg_match('/[0-9]+/', $str, $match);
echo ($match[0] * 1024 * 1024); // <--This is MB converted to bytes
精彩评论