【问题标题】:PHP filesize() On Files > 2 GBPHP filesize() 在文件 > 2 GB
【发布时间】:2012-03-09 21:45:38
【问题描述】:

我一直在努力研究如何在 PHP 中获取 >= 2 GB 的文件的有效文件大小。

示例
在这里,我使用 filesize() 函数检查 3,827,394,560 字节的文件大小:

echo "The file is " . filesize('C:\MyFile.rar') . " bytes.";

结果
这是它返回的内容:

文件为-467572736字节。

背景
PHP 使用有符号整数,这意味着它可以表示的最大数字是 2,147,483,647 (+/- 2 GB)。
这就是它的局限性。

【问题讨论】:

标签: php filesize signed


【解决方案1】:

我尝试过并且显然有效的解决方案是使用 COM FileObject 的“大小”属性。我不完全确定它使用什么类型。

这是我的代码:

function real_filesize($file_path)
{
    $fs = new COM("Scripting.FileSystemObject");
    return $fs->GetFile($file_path)->Size;
}

简称如下:

$file = 'C:\MyFile.rar';
$size = real_filesize($file);
echo "The size of the file is: $size";

结果

文件大小为:3,827,394,560字节

【讨论】:

  • 仅供参考 COM 对象仅表示窗口
  • 这个问题是关于“C:\”中的一个文件,所以他假设环境是Windows。
  • @Juanma 假设?提出这个问题的同一个人几秒钟后发布了这个答案。但是,如果您遇到这个问题并且碰巧偶然发现了这个页面,那么出于显而易见的原因,您最好使用与操作系统无关的解决方案。
  • @MikeB 完全正确,像 Borealid 指出的跨平台解决方案可能更可取,但我个人认为这种方法可能会稍微优化一些。我在几秒钟后发布它的原因是因为我已经找到了它的答案,但想看到更多关于它的意见,并分享我的 Windows 平台解决方案。我在网络上的其他任何地方都没有看到这个解决方案。
  • @RenéSackers 您的解决方案和 Borealid 提供的解决方案都在手册中filesize() 下。 php.net/manual/en/function.filesize.php#104101us.php.net/manual/en/function.filesize.php#102135
【解决方案2】:

http://us.php.net/manual/en/function.filesize.php#102135 提供了一种在 PHP 中查找大于 2GB 的文件大小的完整且正确的方法,而不依赖于特定于操作系统的接口。

它的要点是您首先使用filesize 获取“低”位,然后打开+查找文件以确定它包含多少个 2GB 的倍数(“高”位)。

【讨论】:

  • 有趣,但这不是没有优化吗?是的,它是跨平台的,我会给你。
  • 使用 BigFileTools insted,它为所有平台解决了这个问题,并且经过了全面测试。 github.com/jkuchar/BigFileTools
【解决方案3】:

我使用了一种不同的方法,节省了宝贵的服务器资源, 看看我的 GitHub 存储库 github.com/eladkarako/download.eladkarako.com

这是一个简单完整的下载仪表板,克服filesize错误使用客户端head-request,当然,它不会嵌入到页面的HTML源中,但会在一段时间后渲染(*固定),所以它更适合hmm... ,可以说,轻松场景..

为使该解决方案可用,应添加 Apache .htaccess(或 PHP 中的标头),以允许客户端使用 Content-Length 值。

基本上您可以将.htaccess 精简为只允许Content-Length 删除其他CORS 规则.. 使网站更安全。

没有使用 jQuery,整个内容都是在我的三星文本编辑器中编写并通过 FTP 从我的智能手机上传的,在我的 MILUIM.. 的 1.5 小时火车车程中然而,仍然无可挑剔 ;)

【讨论】:

    【解决方案4】:

    我有一个运行良好的“hacky”解决方案。

    请看THIS function 我是怎么做的,您还需要包括this class 才能正常工作或根据您的需要进行更改。

    示例:

    include_once 'class.os.php';
    include_once 'function.filesize.32bit.php';
    
    // Must be real path to file
    $file = "/home/username/some-folder/yourfile.zip";
    echo get_filesize($file);
    

    此功能不是理想的解决方案,但工作原理如下:

    1. 首先检查shell_exec 是否在PHP 中启用。如果启用,它将通过 shell 命令检查实际文件大小。
    2. 如果 shell 失败且操作系统为 64 位,将返回正常的filesize() 信息
    3. 如果是 32bit 将进入“分块”方法并计算文件大小读取购买。

    注意!

    Alfter 以字符串格式保存结果可以轻松计算,因为 PHP 可以计算字符串,但是如果您将超过 2GB 的结果转换为整数,您将遇到与以前相同的问题。

    警告!

    分块真的很慢,如果你想循环它,你会出现内存泄漏或脚本可能需要几分钟才能完成读取所有文件。如果您在启用了shell_exec 的服务器上使用此功能,您将获得超快的阅读速度。

    附言

    如果您对此处的更改有任何想法并且改进者随时提交。

    【讨论】:

      【解决方案5】:

      对于碰巧在 linux 主机上的任何人,我找到的最简单的解决方案是使用:

      exec("stat --format=\"%s\" \"$file\"");
      

      这假定文件名中没有引号或换行符,并且在技术上返回一个字符串而不是我想的一个数字,但它适用于这种方法以获得 human readable file size.

      我测试过的最大文件约为 3.6 GB。

      【讨论】:

        【解决方案6】:

        我知道这是一个老版本,但我使用的是 PHP x64 5.5.38(目前)并且不想升级到最新的 7.x 版本。

        我确实阅读了所有这些关于查找大于 2GB 的文件大小的帖子,但所有解决方案对于大量文件来说都非常慢。

        所以,昨天我创建了 C/C++ PHP 扩展“php_filesize.dll”,它使用 C/C++ 的强大功能通过我找到的一些方法来查找文件大小,它也兼容 UTF-8 并且非常快。

        你可以试试: http://www.jobnik.net/files/PHP/php_filesize.zip

        用法:

        方法:

        0 - 使用 GetFileAttributesEx

        1 - 使用 CreateFile

        2 - 使用 FindFirstFile

        -1 - 使用 stat64(默认和可选)

        $fsize = php_filesize("文件路径", $method_optional);

        • 以字符串类型返回文件大小,最大为 9 PetaByte

        学分:

        FileSize 方法:Check the file-size without opening file in C++?

        UTF-8 支持:https://github.com/kenjiuno/php-wfio

        【讨论】:

          【解决方案7】:

          为了获得正确的文件大小,我经常使用几个月前自己编写的这段代码。我的代码使用:exec/com/stat(如果有)。我知道它的局限性,但这是一个很好的起点。最好的办法是在 64 位架构上使用 filesize()

          <?php
            ######################################################################
            # Human size for files smaller or bigger than 2 GB on 32 bit Systems #
            # size.php - 1.3 - 21.09.2015 - Alessandro Marinuzzi - www.alecos.it #
            ######################################################################
            function showsize($file) {
              if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
                if (class_exists("COM")) {
                  $fsobj = new COM('Scripting.FileSystemObject');
                  $f = $fsobj->GetFile(realpath($file));
                  $size = $f->Size;
                } else {
                  $size = trim(@exec("for %F in (\"" . $file . "\") do @echo %~zF"));
                }
              } elseif (PHP_OS == 'Darwin') {
                $size = trim(@exec("stat -f %z " . $file));
              } else {
                $size = trim(@exec("stat -c %s " . $file));
              }
              if ((!is_numeric($size)) || ($size < 0)) {
                $size = filesize($file);
              }
              if ($size < 1024) {
                echo $size . ' Byte';
              } elseif ($size < 1048576) {
                echo number_format(round($size / 1024, 2), 2) . ' KB';
              } elseif ($size < 1073741824) {
                echo number_format(round($size / 1048576, 2), 2) . ' MB';
              } elseif ($size < 1099511627776) {
                echo number_format(round($size / 1073741824, 2), 2) . ' GB';
              } elseif ($size < 1125899906842624) {
                echo number_format(round($size / 1099511627776, 2), 2) . ' TB';
              } elseif ($size < 1152921504606846976) {
                echo number_format(round($size / 1125899906842624, 2), 2) . ' PB';
              } elseif ($size < 1180591620717411303424) {
                echo number_format(round($size / 1152921504606846976, 2), 2) . ' EB';
              } elseif ($size < 1208925819614629174706176) {
                echo number_format(round($size / 1180591620717411303424, 2), 2) . ' ZB';
              } else {
                echo number_format(round($size / 1208925819614629174706176, 2), 2) . ' YB';
              }
            }
          ?>
          
          <?php include("php/size.php"); ?>
          
          <?php showsize("files/VeryBigFile.tar"); ?>
          

          我希望这会有所帮助。

          【讨论】:

            猜你喜欢
            • 2011-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-16
            • 1970-01-01
            • 2013-09-02
            • 1970-01-01
            相关资源
            最近更新 更多