PHP x86 How to get filesize of > 2 GB file without

2019-01-04 01:34发布

I need to get the file size of a file over 2 GB in size. (testing on 4.6 GB file). Is there any way to do this without an external program?

Current status:

  • filesize(), stat() and fseek() fails
  • fread() and feof() works

There is a possibility to get the file size by reading the file content (extremely slow!).

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

I know how to get it on 64-bit platforms (using fseek($fp, 0, SEEK_END) and ftell()), but I need solution for 32-bit platform.


Solution: I've started open-source project for this.

Big File Tools

Big File Tools is a collection of hacks that are needed to manipulate files over 2 GB in PHP (even on 32-bit systems).

14条回答
Emotional °昔
2楼-- · 2019-01-04 02:07

One option would be to seek to the 2gb mark and then read the length from there...

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;
}

So basically that seeks to the largest positive signed integer representable in PHP (2gb for a 32 bit system), and then reads from then on using 8kb blocks (which should be a fair tradeoff for best memory efficiency vs disk transfer efficiency).

Also note that I'm not adding $chunksize to size. The reason is that fread may actually return more or fewer bytes than $chunksize depending on a number of possibilities. So instead, use strlen to determine the length of the parsed string.

查看更多
放荡不羁爱自由
3楼-- · 2019-01-04 02:07

Below code works OK for any filesize on any version of 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
查看更多
登录 后发表回答