PHP x86 如何在没有外部程序的情况下获取> 2 GB 文件的文件大小?

2022-08-30 16:38:40

我需要获取大小超过 2 GB 的文件的文件大小。(在 4.6 GB 文件上测试)。有没有办法在没有外部程序的情况下做到这一点?

现状:

  • filesize(),并失败stat()fseek()
  • fread()和作品feof()

可以通过读取文件内容来获取文件大小(非常慢!

$size = (float) 0;
$chunksize = 1024 * 1024;
while (!feof($fp)) {
    fread($fp, $chunksize);
    $size += (float) $chunksize;
}
return $size;

我知道如何在64位平台上获得它(使用和),但我需要32位平台的解决方案。fseek($fp, 0, SEEK_END)ftell()


溶液:我已经为此启动了开源项目。

大文件工具

大文件工具是操作 PHP 中超过 2 GB 的文件(即使在 32 位系统上)所需的黑客集合。


答案 1

这里有一种可能的方法:

它首先尝试使用适合平台的 shell 命令(Windows shell 替换修饰符或 *nix/Mac 命令)。如果失败,它会尝试 COM(如果在 Windows 上),最后回退到 。statfilesize()

/*
 * This software may be modified and distributed under the terms
 * of the MIT license.
 */

function filesize64($file)
{
    static $iswin;
    if (!isset($iswin)) {
        $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
    }

    static $exec_works;
    if (!isset($exec_works)) {
        $exec_works = (function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') == 'EXEC');
    }

    // try a shell command
    if ($exec_works) {
        $cmd = ($iswin) ? "for %F in (\"$file\") do @echo %~zF" : "stat -c%s \"$file\"";
        @exec($cmd, $output);
        if (is_array($output) && ctype_digit($size = trim(implode("\n", $output)))) {
            return $size;
        }
    }

    // try the Windows COM interface
    if ($iswin && class_exists("COM")) {
        try {
            $fsobj = new COM('Scripting.FileSystemObject');
            $f = $fsobj->GetFile( realpath($file) );
            $size = $f->Size;
        } catch (Exception $e) {
            $size = null;
        }
        if (ctype_digit($size)) {
            return $size;
        }
    }

    // if all else fails
    return filesize($file);
}

答案 2

我已经启动了名为Big File Tools的项目它被证明可以在Linux,Mac和Windows上工作(甚至是32位变体)。即使对于大型文件(>4GB),它也提供字节精确的结果。在内部,它使用砖/数学 - 任意精度的算术库。

使用作曲家安装它。

composer install jkuchar/BigFileTools

并使用它:

<?php
$file = BigFileTools\BigFileTools::createDefault()->getFile(__FILE__);
echo $file->getSize() . " bytes\n";

结果是 BigInteger,因此您可以使用结果进行计算

$sizeInBytes = $file->getSize();
$sizeInMegabytes = $sizeInBytes->toBigDecimal()->dividedBy(1024*1024, 2, \Brick\Math\RoundingMode::HALF_DOWN);    
echo "Size is $sizeInMegabytes megabytes\n";

大文件工具内部使用驱动程序来可靠地确定所有平台上的确切文件大小。以下是可用驱动程序的列表(更新于 2016-02-05)

| Driver           | Time (s) ↓          | Runtime requirements | Platform 
| ---------------  | ------------------- | --------------       | ---------
| CurlDriver       | 0.00045299530029297 | CURL extension       | -
| NativeSeekDriver | 0.00052094459533691 | -                    | -
| ComDriver        | 0.0031449794769287  | COM+.NET extension   | Windows only
| ExecDriver       | 0.042937040328979   | exec() enabled       | Windows, Linux, OS X
| NativeRead       | 2.7670161724091     | -                    | -

您可以将 BigFileTools 与其中任何一个一起使用,或者默认情况下选择最快的可用 (BigFileTools::createDefault())

 use BigFileTools\BigFileTools;
 use BigFileTools\Driver;
 $bigFileTools = new BigFileTools(new Driver\CurlDriver());

推荐