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

Hon*_*hař 24 php file-io x86 filesize large-files

我需要获得大小超过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;
Run Code Online (Sandbox Code Playgroud)

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


解决方案:我已经为此启动了开源项目.

大文件工具

Big File Tools是在PHP中操作超过2 GB的文件所需的hacks集合(即使在32位系统上).

Uns*_*ned 21

这是一种可能的方法:

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

/*
 * 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 不,是超级!但这只是解决方案的一部分,因为问题是如何在没有外部程序的情况下获取文件大小...(所有网络服务器都不允许使用“exec”) (2认同)

Hon*_*hař 7

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

使用composer安装它.

composer install jkuchar/BigFileTools
Run Code Online (Sandbox Code Playgroud)

并使用它:

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

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

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

Big File Tools内部使用驱动程序可靠地确定所有平台上的确切文件大小.以下是可用驱动程序列表(更新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     | -                    | -
Run Code Online (Sandbox Code Playgroud)

你可以使用BigFileTools中的任何一个或默认选择最快的(BigFileTools::createDefault())

 use BigFileTools\BigFileTools;
 use BigFileTools\Driver;
 $bigFileTools = new BigFileTools(new Driver\CurlDriver());
Run Code Online (Sandbox Code Playgroud)