web-dev-qa-db-ja.com

PHP x86外部プログラムなしで2GBを超えるファイルのファイルサイズを取得するにはどうすればよいですか?

2GBを超えるサイズのファイルのファイルサイズを取得する必要があります。 (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ビットプラットフォームで(fseek($fp, 0, SEEK_END)ftell()を使用して)取得する方法は知っていますが、32ビットプラットフォーム用のソリューションが必要です。


解決策:私はこのためのオープンソースプロジェクトを開始しました。

ビッグファイルツール

Big File Toolsは、PHP(32ビットシステムでも)で2GBを超えるファイルを操作するために必要なハックのコレクションです。

24
Honza Kuchař

Big File Tools というプロジェクトを開始しました。 Linux、Mac、Windows(32ビットバリアントでも)で動作するのは 証明済み です。巨大なファイル(> 4GB)でもバイト精度の結果を提供します。内部的には brick/math -任意精度の算術ライブラリを使用します。

composer を使用してインストールします。

_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";
_

Big File Toolsは内部でドライバーを使用して、すべてのプラットフォームで正確なファイルサイズを確実に決定します。利用可能なドライバーのリストは次のとおりです(2016年2月5日更新)

_| 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());
_
8
Honza Kuchař

考えられる方法の1つは次のとおりです。

最初に、プラットフォームに適したシェルコマンド(Windowsシェル置換修飾子または* 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);
}
21
Unsigned
<?php
  ######################################################################
  # Human size for files smaller or bigger than 2 GB on 32 bit Systems #
  # size.php - 1.1 - 17.01.2012 - 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));
        $file = $f->Size;
      } else {
        $file = trim(exec("for %F in (\"" . $file . "\") do @echo %~zF"));
      }
    } elseif (PHP_OS == 'Darwin') {
      $file = trim(Shell_exec("stat -f %z " . escapeshellarg($file)));
    } elseif ((PHP_OS == 'Linux') || (PHP_OS == 'FreeBSD') || (PHP_OS == 'Unix') || (PHP_OS == 'SunOS')) {
      $file = trim(Shell_exec("stat -c%s " . escapeshellarg($file)));
    } else {
      $file = filesize($file);
    }
    if ($file < 1024) {
      echo $file . ' Byte';
    } elseif ($file < 1048576) {
      echo round($file / 1024, 2) . ' KB';
    } elseif ($file < 1073741824) {
      echo round($file / 1048576, 2) . ' MB';
    } elseif ($file < 1099511627776) {
      echo round($file / 1073741824, 2) . ' GB';
    } elseif ($file < 1125899906842624) {
      echo round($file / 1099511627776, 2) . ' TB';
    } elseif ($file < 1152921504606846976) {
      echo round($file / 1125899906842624, 2) . ' PB';
    } elseif ($file < 1180591620717411303424) {
      echo round($file / 1152921504606846976, 2) . ' EB';
    } elseif ($file < 1208925819614629174706176) {
      echo round($file / 1180591620717411303424, 2) . ' ZB';
    } else {
      echo round($file / 1208925819614629174706176, 2) . ' YB';
    }
  }
?>

次のように使用します。

<?php include("php/size.php"); ?>

そして、あなたが望む場所:

<?php showsize("files/VeryBigFile.rar"); ?>

あなたがそれを改善したいなら、あなたは大歓迎です!

私は、32ビットphpで大きなファイルのファイルサイズを取得するためだけにLinux/Unix用の素晴らしいスリムなソリューションを見つけました。

$file = "/path/to/my/file.tar.gz";
$filesize = exec("stat -c %s ".$file);

$filesizeを文字列として処理する必要があります。ファイルサイズがPHP_INT_MAXより大きい場合、intとしてキャストしようとすると、filesize = PHP_INT_MAXになります。

しかし、文字列として扱われますが、次の人間が読める形式のアルゴリズムは機能します。

formatBytes($filesize);

public function formatBytes($size, $precision = 2) {
    $base = log($size) / log(1024);
    $suffixes = array('', 'k', 'M', 'G', 'T');
    return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
}

したがって、4Gbを超えるファイルの出力は次のとおりです。

4.46G
2
steven
$file_size=sprintf("%u",filesize($working_dir."\\".$file));

これは、Windowsボックスで機能します。

私はここでバグログを調べていました: https://bugs.php.net/bug.php?id=63618 そしてこの解決策を見つけました。

2
Matt Smith

1つのオプションは、2 GBのマークを探し、そこから長さを読み取ることです...

function getTrueFileSize($filename) {
    $size = filesize($filename);
    if ($size === false) {
        $fp = fopen($filename, 'r');
        if (!$fp) {
            return false;
        }
        $offset = PHP_INT_MAX - 1;
        $size = (float) $offset;
        if (!fseek($fp, $offset)) {
            return false;
        }
        $chunksize = 8192;
        while (!feof($fp)) {
            $size += strlen(fread($fp, $chunksize));
        }
    } elseif ($size < 0) {
        // Handle overflowed integer...
        $size = sprintf("%u", $size);
    }
    return $size;
}

つまり、基本的には、PHP(32ビットシステムの場合は2GB)で表現可能な最大の正符号付き整数を探し、それ以降は8kbブロックを使用して読み取ります(これは、最良のメモリとの公正なトレードオフになるはずです)。効率とディスク転送効率)。

また、サイズに$chunksizeを追加していないことにも注意してください。その理由は、多くの可能性に応じて、freadが実際に$chunksizeよりも多いバイトまたは少ないバイトを返す可能性があるためです。したがって、代わりに、strlenを使用して、解析された文字列の長さを決定します。

0
ircmaxell

これを行う最も簡単な方法は、数値に最大値を追加することです。これは、x86プラットフォームで長い数値が2 ^ 32を追加することを意味します。

if($size < 0) $size = pow(2,32) + $size;

例:Big_File.exe-3,30Gb(3.554.287.616 b)関数は-740679680を返すため、2 ^ 32(4294967296)を追加して3554287616を取得します。

システムが負の符号に1ビットのメモリを予約しているため、負の数が得られます。そのため、負または正の数の最大値が2 ^ 31(2.147.483.648 = 2G)になります。システムがこの最大値に達すると、システムは停止せず、最後に予約されたビットを上書きするだけで、数値は強制的に負になります。簡単に言うと、最大の正の数を超えると、最大の負の数に強制されるため、2147483648 + 1 = -2147483648になります。さらに加算すると、ゼロに向かって、また最大数に向かって進みます。

ご覧のとおり、ループを閉じる最大数と最小数の円のようなものです。

X86アーキテクチャが1ティックで「ダイジェスト」できる最大数の合計は2 ^ 32 = 4294967296 = 4Gです。その数がそれより少ない限り、この単純なトリックは常に機能します。数値が大きい場合は、ループポイントを通過した回数を把握し、それを2 ^ 32で乗算して、結果に追加する必要があります。

$size = pow(2,32) * $loops_count + $size;

もちろん、基本的なPHP関数では、これを行うのは非常に困難です。ループポイントを通過した回数を示す関数がないため、4ギガを超えるファイルでは機能しません。

0

FTPサーバーがある場合は、fsockopenを使用できます。

$socket = fsockopen($hostName, 21);
$t = fgets($socket, 128);
fwrite($socket, "USER $myLogin\r\n");
$t = fgets($socket, 128);
fwrite($socket, "PASS $myPass\r\n");
$t = fgets($socket, 128);
fwrite($socket, "SIZE $fileName\r\n");
$t = fgets($socket, 128);
$fileSize=floatval(str_replace("213 ","",$t));
echo $fileSize;
fwrite($socket, "QUIT\r\n");
fclose($socket); 

ftp_size ページのコメントとして見つかりました)

0
dave1010

いくつかの回答が示唆しているように、filesize()が負を返すかどうかをチェックすることによって、32ビットシステム上のファイルのサイズを確実に取得することはできません。これは、ファイルが32ビットシステムで4〜6ギグの場合、ファイルサイズは正の数を報告し、次に6〜8の負の数を報告し、次に8〜10の正の数を報告するためです。ある意味でループします。

そのため、32ビットシステムで確実に機能する外部コマンドを使用して立ち往生しています。

ただし、非常に便利なツールの1つは、ファイルサイズが特定のサイズよりも大きいかどうかを確認する機能であり、非常に大きなファイルでもこれを確実に実行できます。

以下は50メガバイトをシークし、1バイトを読み取ろうとします。私の低スペックテストマシンでは非常に高速で、サイズが2ギガよりはるかに大きい場合でも確実に動作します。

これを使用して、ファイルが2147483647バイト(2147483648は32ビットシステムでは最大整数)より大きいかどうかを確認してから、ファイルを別の方法で処理するか、アプリに警告を発行させることができます。

function isTooBig($file){
        $fh = @fopen($file, 'r');
        if(! $fh){ return false; }
        $offset = 50 * 1024 * 1024; //50 megs
        $tooBig = false;
        if(fseek($fh, $offset, SEEK_SET) === 0){
                if(strlen(fread($fh, 1)) === 1){
                        $tooBig = true;
                }
        } //Otherwise we couldn't seek there so it must be smaller

        fclose($fh);
        return $tooBig;
}
0
Mark Maunder

IEEE doubleが使用されている場合(ほとんどのシステム)、〜4EB(エクサバイト= 10 ^ 18バイト)未満のファイルサイズは正確な数値のdoubleに収まります(標準の算術演算を使用しても精度が低下することはありません)。

0
kravčo

BigFileToolsclass/answerを繰り返しました:
-一部のプラットフォーム(Synology NASなど)はCurlのFTPプロトコルをサポートしていないため、curlメソッドを無効にするオプション
-余分な非posixですが、より正確なsizeExecの実装、ディスク上のサイズの代わりに、duの代わりにstatを使用して実際のファイルサイズが返されます
-大きなファイル(> 4GB)の正しいサイズの結果とsizeNativeSeekのほぼ同じ速度
-デバッグメッセージオプション

<?php

/**
 * Class for manipulating files bigger than 2GB
 * (currently supports only getting filesize)
 *
 * @author Honza Kuchař
 * @license New BSD
 * @encoding UTF-8
 * @copyright Copyright (c) 2013, Jan Kuchař
 */
class BigFileTools {

    /**
     * Absolute file path
     * @var string
     */
    protected $path;

    /**
     * Use in BigFileTools::$mathLib if you want to use BCMath for mathematical operations
     */
    const MATH_BCMATH = "BCMath";

    /**
     * Use in BigFileTools::$mathLib if you want to use GMP for mathematical operations
     */
    const MATH_GMP = "GMP";

    /**
     * Which mathematical library use for mathematical operations
     * @var string (on of constants BigFileTools::MATH_*)
     */
    public static $mathLib;

    /**
     * If none of fast modes is available to compute filesize, BigFileTools uses to compute size very slow
     * method - reading file from 0 byte to end. If you want to enable this behavior,
     * switch fastMode to false (default is true)
     * @var bool
     */
    public static $fastMode = true;

  //on some platforms like Synology NAS DS214+ DSM 5.1 FTP Protocol for curl is not working or disabled
  // you will get an error like "Protocol file not supported or disabled in libcurl"
    public static $FTPProtocolCurlEnabled = false; 
  public static $debug=false; //shows some debug/error messages
  public static $posix=true; //more portable but it shows size on disk not actual filesize so it's less accurate: 0..clustersize in bytes inaccuracy

    /**
     * Initialization of class
     * Do not call directly.
     */
    static function init() {
        if (function_exists("bcadd")) {
            self::$mathLib = self::MATH_BCMATH;
        } elseif (function_exists("gmp_add")) {
            self::$mathLib = self::MATH_GMP;
        } else {
            throw new BigFileToolsException("You have to install BCMath or GMP. There mathematical libraries are used for size computation.");
        }
    }

    /**
     * Create BigFileTools from $path
     * @param string $path
     * @return BigFileTools
     */
    static function fromPath($path) {
        return new self($path);
    }

    static function debug($msg) {
        if (self::$debug) echo $msg;
    }

    /**
     * Gets basename of file (example: for file.txt will return "file")
     * @return string
     */
    public function getBaseName() {
        return pathinfo($this->path, PATHINFO_BASENAME);
    }

    /**
     * Gets extension of file (example: for file.txt will return "txt")
     * @return string
     */
    public function getExtension() {
        return pathinfo($this->path, PATHINFO_EXTENSION);
    }


    /**
     * Gets extension of file (example: for file.txt will return "file.txt")
     * @return string
     */
    public function getFilename() {
        return pathinfo($this->path, PATHINFO_FILENAME);
    }

    /**
     * Gets path to file of file (example: for file.txt will return path to file.txt, e.g. /home/test/)
     * ! This will call absolute path!
     * @return string
     */
    public function getDirname() {
        return pathinfo($this->path, PATHINFO_DIRNAME);
    }

    /**
     * Gets md5 checksum of file content
     * @return string
     */
    public function getMd5() {
        return md5_file($this->path);
    }

    /**
     * Gets sha1 checksum of file content
     * @return string
     */
    public function getSha1() {
        return sha1_file($this->path);
    }

    /**
     * Constructor - do not call directly
     * @param string $path
     */
    function __construct($path, $absolutizePath = true) {
        if (!static::isReadableFile($path)) {
            throw new BigFileToolsException("File not found at $path");
        }

        if($absolutizePath) {
            $this->setPath($path);
        }else{
            $this->setAbsolutePath($path);
        }
    }

    /**
     * Tries to absolutize path and than updates instance state
     * @param string $path
     */
    function setPath($path) {

        $this->setAbsolutePath(static::absolutizePath($path));
    }

    /**
     * Setts absolute path
     * @param string $path
     */
    function setAbsolutePath($path) {
        $this->path = $path;
    }

    /**
     * Gets current filepath
     * @return string
     */
    function getPath($a = "") {
        if(a != "") {
            trigger_error("getPath with absolutizing argument is deprecated!", E_USER_DEPRECATED);
        }

        return $this->path;
    }

    /**
     * Converts relative path to absolute
     */
    static function absolutizePath($path) {

        $path = realpath($path);
        if(!$path) {
            // TODO: use hack like http://stackoverflow.com/questions/4049856/replace-phps-realpath or http://www.php.net/manual/en/function.realpath.php#84012
            //       probaly as optinal feature that can be turned on when you know, what are you doing

            throw new BigFileToolsException("Not possible to resolve absolute path.");
        }
        return $path;
    }

    static function isReadableFile($file) {
        // Do not use is_file
        // @link https://bugs.php.net/bug.php?id=27792
        // $readable = is_readable($file); // does not always return correct value for directories

        $fp = @fopen($file, "r"); // must be file and must be readable
        if($fp) {
            fclose($fp);
            return true;
        }
        return false;
    }

    /**
     * Moves file to new location / rename
     * @param string $dest
     */
    function move($dest) {
        if (move_uploaded_file($this->path, $dest)) {
            $this->setPath($dest);
            return TRUE;
        } else {
            @unlink($dest); // needed in PHP < 5.3 & Windows; intentionally @
            if (rename($this->path, $dest)) {
                $this->setPath($dest);
                return TRUE;
            } else {
                if (copy($this->path, $dest)) {
                    unlink($this->path); // delete file
                    $this->setPath($dest);
                    return TRUE;
                }
                return FALSE;
            }
        }
    }

    /**
     * Changes path of this file object
     * @param string $dest
     */
    function relocate($dest) {
        trigger_error("Relocate is deprecated!", E_USER_DEPRECATED);
        $this->setPath($dest);
    }

    /**
     * Size of file
     *
     * Profiling results:
     *  sizeCurl        0.00045299530029297
     *  sizeNativeSeek  0.00052094459533691
     *  sizeCom         0.0031449794769287
     *  sizeExec        0.042937040328979
     *  sizeNativeRead  2.7670161724091
     *
     * @return string | float
     * @throws BigFileToolsException
     */
    public function getSize($float = false) {
        if ($float == true) {
            return (float) $this->getSize(false);
        }

        $return = $this->sizeCurl();
        if ($return) {
      $this->debug("sizeCurl succeeded");
            return $return;
        }
    $this->debug("sizeCurl failed");

        $return = $this->sizeNativeSeek();
        if ($return) {
      $this->debug("sizeNativeSeek succeeded");
            return $return;
        }
    $this->debug("sizeNativeSeek failed");

        $return = $this->sizeCom();
        if ($return) {
      $this->debug("sizeCom succeeded");
            return $return;
        }
    $this->debug("sizeCom failed");

        $return = $this->sizeExec();
        if ($return) {
      $this->debug("sizeExec succeeded");
            return $return;
        }
    $this->debug("sizeExec failed");

        if (!self::$fastMode) {
            $return = $this->sizeNativeRead();
            if ($return) {
        $this->debug("sizeNativeRead succeeded");
                return $return;
            }
      $this->debug("sizeNativeRead failed");
        }

        throw new BigFileToolsException("Can not size of file $this->path !");
    }

    // <editor-fold defaultstate="collapsed" desc="size* implementations">
    /**
     * Returns file size by using native fseek function
     * @see http://www.php.net/manual/en/function.filesize.php#79023
     * @see http://www.php.net/manual/en/function.filesize.php#102135
     * @return string | bool (false when fail)
     */
    protected function sizeNativeSeek() {
        $fp = fopen($this->path, "rb");
        if (!$fp) {
            return false;
        }

        flock($fp, LOCK_SH);
    $result= fseek($fp, 0, SEEK_END);

    if ($result===0) {
      if (PHP_INT_SIZE < 8) {
        // 32bit
        $return = 0.0;
        $step = 0x7FFFFFFF;
        while ($step > 0) {
          if (0 === fseek($fp, - $step, SEEK_CUR)) {
            $return += floatval($step);
          } else {
            $step >>= 1;
          }
        }
      }
      else { //64bit
        $return = ftell($fp);
      }
    }
    else $return = false;

    flock($fp, LOCK_UN);
    fclose($fp);
    return $return;
    }

    /**
     * Returns file size by using native fread function
     * @see http://stackoverflow.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5504829#5504829
     * @return string | bool (false when fail)
     */
    protected function sizeNativeRead() {
        $fp = fopen($this->path, "rb");
        if (!$fp) {
            return false;
        }
        flock($fp, LOCK_SH);

        rewind($fp);
        $offset = PHP_INT_MAX - 1;

        $size = (string) $offset;
        if (fseek($fp, $offset) !== 0) {
            flock($fp, LOCK_UN);
            fclose($fp);
            return false;
        }
        $chunksize = 1024 * 1024;
        while (!feof($fp)) {
            $read = strlen(fread($fp, $chunksize));
            if (self::$mathLib == self::MATH_BCMATH) {
                $size = bcadd($size, $read);
            } elseif (self::$mathLib == self::MATH_GMP) {
                $size = gmp_add($size, $read);
            } else {
                throw new BigFileToolsException("No mathematical library available");
            }
        }
        if (self::$mathLib == self::MATH_GMP) {
            $size = gmp_strval($size);
        }
        flock($fp, LOCK_UN);
        fclose($fp);
        return $size;
    }

    /**
     * Returns file size using curl module
     * @see http://www.php.net/manual/en/function.filesize.php#100434
     * @return string | bool (false when fail or cUrl module not available)
     */
    protected function sizeCurl() {
        // curl solution - cross platform and really cool :)
        if (self::$FTPProtocolCurlEnabled && function_exists("curl_init")) {
            $ch = curl_init("file://" . $this->path);
            curl_setopt($ch, CURLOPT_NOBODY, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HEADER, true);
            $data = curl_exec($ch);
      if ($data=="" || empty($data)) $this->debug(stripslashes(curl_error($ch)));
            curl_close($ch);
            if ($data !== false && preg_match('/Content-Length: (\d+)/', $data, $matches)) {
                return (string) $matches[1];
            }
        } else {
            return false;
        }
    }

    /**
     * Returns file size by using external program (exec needed)
     * @see http://stackoverflow.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5502328#5502328
     * @return string | bool (false when fail or exec is disabled)
     */
    protected function sizeExec() {
        // filesize using exec
        if (function_exists("exec")) {

            if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { // Windows
                // Try using the NT substition modifier %~z
        $escapedPath = escapeshellarg($this->path);
                $size = trim(exec("for %F in ($escapedPath) do @echo %~zF"));
            }else{ // other OS
                // If the platform is not Windows, use the stat command (should work for *nix and MacOS)
        if (self::$posix) {
          $tmpsize=trim(exec("du \"".$this->path."\" | cut -f1")); 
          //du returns blocks/KB
          $size=(int)$tmpsize*1024; //make it bytes
        }
        else $size=trim(exec('stat "'.$this->path.'" | grep -i -o -E "Size: ([0-9]+)" | cut -d" " -f2'));

        if (self::$debug) var_dump($size);
        return $size;
            }

        }
        return false;
    }

    /**
     * Returns file size by using Windows COM interface
     * @see http://stackoverflow.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5502328#5502328
     * @return string | bool (false when fail or COM not available)
     */
    protected function sizeCom() {
        if (class_exists("COM")) {
            // Use the Windows COM interface
            $fsobj = new COM('Scripting.FileSystemObject');
            if (dirname($this->path) == '.')
                $this->path = ((substr(getcwd(), -1) == DIRECTORY_SEPARATOR) ? getcwd() . basename($this->path) : getcwd() . DIRECTORY_SEPARATOR . basename($this->path));
            $f = $fsobj->GetFile($this->path);
            return (string) $f->Size;
        }
    }

    // </editor-fold>
}

BigFileTools::init();

class BigFileToolsException extends Exception{}
0
Jan

以下のコードは、PHP/OS/Webserver/Platformの任意のバージョンの任意のファイルサイズで正常に機能します。

// http head request to local file to get file size
$opts = array('http'=>array('method'=>'HEAD'));
$context = stream_context_create($opts);

// change the URL below to the URL of your file. DO NOT change it to a file path.
// you MUST use a http:// URL for your file for a http request to work
// SECURITY - you must add a .htaccess rule which denies all requests for this database file except those coming from local ip 127.0.0.1.
// $tmp will contain 0 bytes, since its a HEAD request only, so no data actually downloaded, we only want file size
$tmp= file_get_contents('http://127.0.0.1/pages-articles.xml.bz2', false, $context);

$tmp=$http_response_header;
foreach($tmp as $rcd) if( stripos(trim($rcd),"Content-Length:")===0 )  $size= floatval(trim(str_ireplace("Content-Length:","",$rcd)));
echo "File size = $size bytes";

// example output
File size = 10082006833 bytes

「dir」/「ls」などのシステム関数を呼び出してそこから情報を取得するなど、使用する関数にいくつかの代替手段を追加することをお勧めします。もちろん、これらはセキュリティの対象です。確認して、最終的には最後の手段として遅い方法に戻すことができます。

0
Jorj