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()
failsfread()
and feof()
worksThere 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 is a collection of hacks that are needed to manipulate files over 2 GB in PHP (even on 32-bit systems).
Here's one possible method:
It first attempts to use a platform-appropriate shell command (Windows shell substitution modifiers or *nix/Mac stat
command). If that fails, it tries COM (if on Windows), and finally falls back to 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); }
I've started project called Big File Tools. It is proven to work on Linux, Mac and Windows (even 32-bit variants). It provides byte-precise results even for huge files (>4GB). Internally it uses brick/math - arbitrary-precision arithmetic library.
Install it using composer.
composer install jkuchar/BigFileTools
and use it:
<?php $file = BigFileTools\BigFileTools::createDefault()->getFile(__FILE__); echo $file->getSize() . " bytes\n";
Result is BigInteger so you can compute with results
$sizeInBytes = $file->getSize(); $sizeInMegabytes = $sizeInBytes->toBigDecimal()->dividedBy(1024*1024, 2, \Brick\Math\RoundingMode::HALF_DOWN); echo "Size is $sizeInMegabytes megabytes\n";
Big File Tools internally uses drivers to reliably determine exact file size on all platforms. Here is list of available drivers (updated 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 | - | -
You can use BigFileTools with any of these or fastest available is chosen by default (BigFileTools::createDefault()
)
use BigFileTools\BigFileTools; use BigFileTools\Driver; $bigFileTools = new BigFileTools(new Driver\CurlDriver());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With