PHP文件大小MB/KB转换

146

如何将PHP的filesize()函数的输出转换为带有MB、KB等格式的好格式?

例如:

  • 如果大小小于1MB,则以KB为单位显示大小。
  • 如果大小在1MB到1GB之间,则以MB为单位显示。
  • 如果大小大于1GB,则以GB为单位显示。

1
请查看以下内容,该内容与 PHP 将字节格式化为千字节、兆字节、吉字节有关:https://dev59.com/A3E85IYBdhLWcg3w_I78 - Code
如果您正在使用WordPress,则可以使用共享函数size_format() - Earlee
如果你不是在使用WordPress(我是!),你可以随时查看https://developer.wordpress.org/reference/functions/size_format/并复制源代码。它定义了一些常量,但一切都应该很容易理解;此外,WordPress代码试图处理国际化/本地化,这可能有些过度(而`number_format()`将在最后完成漂亮格式的工作,而不是使用WP自己的函数)。 - undefined
11个回答

332

这里有一个示例:

<?php
// Snippet from PHP Share: http://www.phpshare.org

    function formatSizeUnits($bytes)
    {
        if ($bytes >= 1073741824)
        {
            $bytes = number_format($bytes / 1073741824, 2) . ' GB';
        }
        elseif ($bytes >= 1048576)
        {
            $bytes = number_format($bytes / 1048576, 2) . ' MB';
        }
        elseif ($bytes >= 1024)
        {
            $bytes = number_format($bytes / 1024, 2) . ' KB';
        }
        elseif ($bytes > 1)
        {
            $bytes = $bytes . ' bytes';
        }
        elseif ($bytes == 1)
        {
            $bytes = $bytes . ' byte';
        }
        else
        {
            $bytes = '0 bytes';
        }

        return $bytes;
}
?>

7
这个答案比下面的其他答案更高效。它避免使用对数函数或连续除法语句来识别单位。 - Ali Gangji
1
这是一个非常出色的解决方案,感谢您提供这个非常棒的函数 - 正是我在寻找的。 - justinhartman
这个函数实际上是不正确的。1KB 等于 1000 字节,因为 Kilo 是1000。 - Aidas
简单明了,只需确保您输入到函数中的字节值未使用number_format格式化即可。哈哈,一直想不明白为什么它无法正常工作,后来才意识到逗号弄乱了我的事情。 - Michael
这太棒了,完美地运作。 - Eben Watts
终于有人写出了快速的PHP代码,避免了调用昂贵的数学函数的所有陷阱!当然,这段代码很容易理解。有时候,简单的代码就是高效的代码。而且使用number_format()这个细节很不错。实际上,看起来WordPress本身也使用了你这个简单函数的变体:https://developer.wordpress.org/reference/functions/size_format/ - undefined

75

更好的是,我从一个插件创建了这个版本:

function filesize_formatted($path)
{
    $size = filesize($path);
    $units = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
    $power = $size > 0 ? floor(log($size, 1024)) : 0;
    return number_format($size / pow(1024, $power), 2, '.', ',') . ' ' . $units[$power];
}

来自filesize() 文档的说明:

由于PHP的整数类型是带符号的,并且许多平台使用32位整数,因此对于文件大小超过2GB的文件,一些文件系统函数可能会返回意外的结果。


1
为什么它更“好看”呢?它几乎和我的版本做了同样的事情,除了对于超过2GB的文件会返回错误的大小(而且OP从未要求剩余电量单位)。 - Alix Axel
6
@AlixAxel,这样更好,因为它只有原来大小的一半,但仍然容易阅读。而且我打赌它会更快。但是嘿,这不是个人问题。我没有自己想到这个。你的版本也很棒!已经给你点赞了 ;) - PiTheNumber
1
Adnan发布了最详细但也是最高效的答案。使用对数函数来确定单位比使用简单的不等式要慢得多。即使在循环中使用连续的除法语句,也比使用对数要快得多。 - Ali Gangji
1
@PiTheNumber 请查看 filesize()函数文档 中的注意事项: “由于PHP的整数类型是带符号的,许多平台使用32位整数,一些文件系统函数对于超过2GB的文件可能返回意外结果”。因为这个原因和其他很多原因,我不相信会有人使用PHP来操作以TB或更高单位大小计算的文件。此外,我怀疑你的函数比Alix Axel的函数更快,因为你使用的pow函数在资源消耗上与Alix使用的log类似。 - trejder
我并没有说它更快或者什么的,只是看起来更好而已。但是出于好玩,我尝试做了一个基准测试,但是我没有得到任何有用的结果。我不应该在codepad上运行它:http://codepad.org/o6cWsjIi - PiTheNumber

43

更加简洁的方法:

function Size($path)
{
    $bytes = sprintf('%u', filesize($path));

    if ($bytes > 0)
    {
        $unit = intval(log($bytes, 1024));
        $units = array('B', 'KB', 'MB', 'GB');

        if (array_key_exists($unit, $units) === true)
        {
            return sprintf('%d %s', $bytes / pow(1024, $unit), $units[$unit]);
        }
    }

    return $bytes;
}

@AliGangji:确实,具体而言成本会增加0.1%到42%不等(这取决于$bytes落入哪个“if”条件中)。 - Alix Axel
@AliGangji:在我上一条评论的基础上,似乎对于小于等于1023字节的值,采用对数方法平均要慢大约40%,但对于1024及以上的值,我得到了稳定的平均值约为0.1%。有趣! - Alix Axel
@AlixAxel 那不是因为 PHP 解析器从底部到顶部分析 if 块,即从单个(最后一个)else 开始,然后通过所有的 elseif 上升,直到最后到达第一个(按顺序)的 if 吗?只是好奇,你为什么会得到这样的结果? - trejder
@trejder:我的代码中只有一个if语句。对于1..1023的值,它比任何大于该值的给定值都要慢得多。我认为这与PHP的log实现有关(毕竟,我使用的是1024进制)。 - Alix Axel
5
我简直不敢相信你们在这个更加简洁优美的答案中争论“对数方程”的“成本”。你们是如何衡量这种差异的?为什么不在应用单位附录之前将函数与>=1024进行比较,如果log如此昂贵的话? - j4k3
显示剩余3条评论

18

我认为这种方法更好。简单而直接。

public function sizeFilter( $bytes )
{
    $label = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB' );
    for( $i = 0; $bytes >= 1024 && $i < ( count( $label ) -1 ); $bytes /= 1024, $i++ );
    return( round( $bytes, 2 ) . " " . $label[$i] );
}

完美,我可以在我的辅助类中使用它,非常感谢。 - Vipertecpro

11

这是基于@adnan的很棒的答案。

更改:

  • 添加了内部filesize()调用
  • 采用return early风格
  • 节省了一次1字节的连接操作

您仍然可以将filesize()调用从函数中提取出来,以获得一个纯字节格式化函数。但这适用于文件。


/**
 * Formats filesize in human readable way.
 *
 * @param file $file
 * @return string Formatted Filesize, e.g. "113.24 MB".
 */
function filesize_formatted($file)
{
    $bytes = filesize($file);

    if ($bytes >= 1073741824) {
        return number_format($bytes / 1073741824, 2) . ' GB';
    } elseif ($bytes >= 1048576) {
        return number_format($bytes / 1048576, 2) . ' MB';
    } elseif ($bytes >= 1024) {
        return number_format($bytes / 1024, 2) . ' KB';
    } elseif ($bytes > 1) {
        return $bytes . ' bytes';
    } elseif ($bytes == 1) {
        return '1 byte';
    } else {
        return '0 bytes';
    }
}

8

所有回答该问题的都使用了1千字节=1024字节,这是错误的!(1 Kibibyte = 1024字节

由于该问题要求转换文件大小,因此应该使用1千字节=1000字节(参见https://wiki.ubuntu.com/UnitsPolicy

function format_bytes($bytes, $precision = 2) {
    $units = array('B', 'KB', 'MB', 'GB');

    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1000));
    $pow = min($pow, count($units) - 1);

    $bytes /= pow(1000, $pow);

    return round($bytes, $precision) . ' ' . $units[$pow];
}

1
这个答案是根据国际单位制标准(除了KB应该是kB)技术上唯一正确的。如果您使用1024作为除数,那么单位应该表示为KiB、MiB、GiB、TiB等。 - MortimerCat

6
这是一个更加简洁的实现方式:
function size2Byte($size) {
    $units = array('KB', 'MB', 'GB', 'TB');
    $currUnit = '';
    while (count($units) > 0  &&  $size > 1024) {
        $currUnit = array_shift($units);
        $size /= 1024;
    }
    return ($size | 0) . $currUnit;
}

3
一个完整的例子。
<?php
    $units = explode(' ','B KB MB GB TB PB');
    echo("<html><body>");
    echo('file size: ' . format_size(filesize("example.txt")));
    echo("</body></html>");


    function format_size($size) {

        $mod = 1024;

        for ($i = 0; $size > $mod; $i++) {
            $size /= $mod;
        }

        $endIndex = strpos($size, ".")+3;

        return substr( $size, 0, $endIndex).' '.$units[$i];
    }
?>

3
function calcSize($size,$accuracy=2) {
    $units = array('b','Kb','Mb','Gb');
    foreach($units as $n=>$u) {
        $div = pow(1024,$n);
        if($size > $div) $output = number_format($size/$div,$accuracy).$u;
    }
    return $output;
}

2
//Get the size in bytes
function calculateFileSize($size)
{
   $sizes = ['B', 'KB', 'MB', 'GB'];
   $count=0;
   if ($size < 1024) {
    return $size . " " . $sizes[$count];
    } else{
     while ($size>1024){
        $size=round($size/1024,2);
        $count++;
    }
     return $size . " " . $sizes[$count];
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接