Filesystem 函数
在线手册:中文 英文
PHP手册

filesize

(PHP 4, PHP 5)

filesize取得文件大小

说明

int filesize ( string $filename )

返回文件大小的字节数,如果出错返回 FALSE 并生成一条 E_WARNING 级的错误。

Note: 因为 PHP 的整数类型是有符号的,并且大多数平台使用 32 位整数,filesize() 函数在碰到大于 2GB 的文件时可能会返回非预期的结果。对于 2GB 到 4GB 之间的文件通常可以使用 sprintf("%u", filesize($file)) 来克服此问题。

Note: 此函数的结果会被缓存。参见 clearstatcache() 以获得更多细节。

Tip

自 PHP 5.0.0 起, 此函数也用于某些 URL 包装器。请参见 Supported Protocols and Wrappers以获得支持 stat() 系列函数功能的包装器列表。

Example #1 filesize() 例子

<?php

// 输出类似:somefile.txt: 1024 bytes

$filename 'somefile.txt';
echo 
$filename ': ' filesize($filename) . ' bytes';

?>

参见 file_exists()

参数

filename

Path to the file.

返回值

Returns the size of the file in bytes, or FALSE (and generates an error of level E_WARNING) in case of an error.

Note: 因为 PHP 的整数类型是有符号整型而且很多平台使用32位整型, 对2GB以上的文件,一些文件系统函数可能返回无法预期的结果 。

范例

Example #2 filesize() example

<?php

// outputs e.g.  somefile.txt: 1024 bytes

$filename 'somefile.txt';
echo 
$filename ': ' filesize($filename) . ' bytes';

?>

错误/异常

失败时抛出E_WARNING警告.

注释

Note: 此函数的结果会被缓存。参见 clearstatcache() 以获得更多细节。

Tip

自 PHP 5.0.0 起, 此函数也用于某些 URL 包装器。请参见 Supported Protocols and Wrappers以获得支持 stat() 系列函数功能的包装器列表。

参见


Filesystem 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: 取得文件大小

用户评论:

yatsynych at gmail dot com (19-Dec-2011 06:13)

<?php
function _format_bytes($a_bytes)
{
    if (
$a_bytes < 1024) {
        return
$a_bytes .' B';
    } elseif (
$a_bytes < 1048576) {
        return
round($a_bytes / 1024, 2) .' KiB';
    } elseif (
$a_bytes < 1073741824) {
        return
round($a_bytes / 1048576, 2) . ' MiB';
    } elseif (
$a_bytes < 1099511627776) {
        return
round($a_bytes / 1073741824, 2) . ' GiB';
    } elseif (
$a_bytes < 1125899906842624) {
        return
round($a_bytes / 1099511627776, 2) .' TiB';
    } elseif (
$a_bytes < 1152921504606846976) {
        return
round($a_bytes / 1125899906842624, 2) .' PiB';
    } elseif (
$a_bytes < 1180591620717411303424) {
        return
round($a_bytes / 1152921504606846976, 2) .' EiB';
    } elseif (
$a_bytes < 1208925819614629174706176) {
        return
round($a_bytes / 1180591620717411303424, 2) .' ZiB';
    } else {
        return
round($a_bytes / 1208925819614629174706176, 2) .' YiB';
    }
}
?>

webmaster at sebastiangrinke dot info (05-Dec-2011 03:32)

Here a little function which provides automated units^^

<?php
function calc_size($path,$size=0,$unit='a',$length=2){
    if(!
is_dir($path)){$size+=filesize($path);}
    else{
     
$dir = opendir($path);
      while(
$f = readdir($dir)){
        if(
is_file($path.DS.$f)){$size+=filesize($path.DS.$f);}
        elseif(
is_dir($path.DS.$f) AND $f!='.' AND $f!='..'){$size=calc_size($path.DS.$f,$size,'',0);}
      }
    }
    if(
$unit==''){return $size;}
    elseif(
$unit=='b' XOR $unit=='a' AND strlen($size) < 4){return number_format($size,$length,',','').' <span title="Byte">Byte</span>';}
    elseif(
$unit=='kb' XOR $unit=='a' AND strlen($size) < 7){return number_format(($size/1024),$length,',','').' <span title="Kilobyte">KiB</span>';}
    elseif(
$unit=='mb' XOR $unit=='a' AND strlen($size) < 10){return number_format(($size/1024/1024),$length,',','').' <span title="Megabyte">MiB</span>';}
    elseif(
$unit=='gb' XOR $unit=='a' AND strlen($size) < 13){return number_format(($size/1024/1024/1024),$length,',','').' <span title="Gigabyte">GiB</span>';}
    elseif(
$unit=='tb' XOR $unit=='a' AND strlen($size) < 16){return number_format(($size/1024/1024/1024/1024),$length,',','').' <span title="Terabyte">TiB</span>';}
    elseif(
$unit=='pb' XOR $unit=='a' AND strlen($size) < 19){return number_format(($size/1024/1024/1024/1024/1024),$length,',','').' <span title="Petabyte">PiB</span>';}
    elseif(
$unit=='eb' XOR $unit=='a' AND strlen($size) < 21){return number_format(($size/1024/1024/1024/1024/1024/1024),$length,',','').' <span title="Exabyte">EiB</span>';}
    elseif(
$unit=='zb' XOR $unit=='a' AND strlen($size) < 24){return number_format(($size/1024/1024/1024/1024/1024/1024/1024),$length,',','').' <span title="Zettabyte">ZiB</span>';}
    elseif(
$unit=='yb' XOR $unit=='a' AND strlen($size) > 24){return number_format(($size/1024/1024/1024/1024/1024/1024/1024/1024),$length,',','').' <span title="Yottabyte">YiB</span>';}
  }
?>

rommel at rommelsantor dot com (19-Nov-2011 08:11)

Extremely simple function to get human filesize.
<?php
function human_filesize($bytes, $decimals = 2) {
 
$sz = 'BKMGTP';
 
$factor = floor((strlen($bytes) - 1) / 3);
  return
sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
?>

Dojung Kim (26-Oct-2011 06:20)

It could be useful for over 2GB files in linux system.
Using awk, I could find real size of its file.

<?php
function filesize_n($path)
{
       
$size = @filesize($path);
        if(
$size < 0 ){
           
ob_start();
           
system('ls -al "'.$path.'" | awk \'BEGIN {FS=" "}{print $5}\'');
           
$size = ob_get_clean();
        }

        return
$size;
}
?>

stachu540 at gmail dot com (30-Aug-2011 05:02)

That is for example how getting filesize with bytes ending.
<?php

function FileSize($file, $setup = null)
{
   
$FZ = ($file && @is_file($file)) ? filesize($file) : NULL;
   
$FS = array("B","kB","MB","GB","TB","PB","EB","ZB","YB");
   
    if(!
$setup && $setup !== 0)
    {
        return
number_format($FZ/pow(1024, $I=floor(log($FZ, 1024))), ($i >= 1) ? 2 : 0) . ' ' . $FS[$I];
    } elseif (
$setup == 'INT') return number_format($FZ);
    else return
number_format($FZ/pow(1024, $setup), ($setup >= 1) ? 2 : 0 ). ' ' . $FS[$setup];
}
?>

swimming at gmx dot de (23-May-2011 08:53)

I found the following to be a nice solution (if you are running Windows) for the >4GB problem. Using the Windows internal Scripting.FileSystemObject you can get the file size using the following code:

<?php
$filesystem
= new COM('Scripting.FileSystemObject');
$file = $filesystem->GetFile($filename);
$size = $file->Size();
?>

The file size will be returned as integer for small files, automatically changing to float for bigger ones. The COM class is part of the PHP core.

Alex Aulbach (31-Mar-2011 08:20)

Note, that the official IEC-prefix for kilobyte, megabyte and so on are KiB, MiB, TiB and so on.

See http://en.wikipedia.org/wiki/Tebibyte

At first glance this may sound like "What the hell? Everybody knows, that we mean 1024 not 1000 and the difference is not too big, so what?". But in about 10 years, the size of harddisks (and files on them) reaches the petabyte-limit and then the difference between PB and PiB is magnificent.

Better to get used to it now. :)

(I added the same note a view days before in http://php.net/manual/en/function.memory-get-usage.php and found it might be also useful here)

arne_elster at web dot de (28-Jan-2011 02:27)

Function that determines a file's size only with PHP functions,
for all files, also those > 4 GB:

<?php

function fsize($file) {
 
// filesize will only return the lower 32 bits of
  // the file's size! Make it unsigned.
 
$fmod = filesize($file);
  if (
$fmod < 0) $fmod += 2.0 * (PHP_INT_MAX + 1);

 
// find the upper 32 bits
 
$i = 0;

 
$myfile = fopen($file, "r");

 
// feof has undefined behaviour for big files.
  // after we hit the eof with fseek,
  // fread may not be able to detect the eof,
  // but it also can't read bytes, so use it as an
  // indicator.
 
while (strlen(fread($myfile, 1)) === 1) {
   
fseek($myfile, PHP_INT_MAX, SEEK_CUR);
   
$i++;
  }

 
fclose($myfile);

 
// $i is a multiplier for PHP_INT_MAX byte blocks.
  // return to the last multiple of 4, as filesize has modulo of 4 GB (lower 32 bits)
 
if ($i % 2 == 1) $i--;
 
 
// add the lower 32 bit to our PHP_INT_MAX multiplier
 
return ((float)($i) * (PHP_INT_MAX + 1)) + $fmod;
}

?>

Anonymous (22-Jan-2011 02:58)

if you recently appended something to file, and closed it then this method will not show appended data:
<?php
// get contents of a file into a string
$filename = "/usr/local/something.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
?>
You should insert a call to clearstatcache() before calling filesize()
I've spent two hours to find that =/

frank (at) haua dot net (16-Jan-2011 02:19)

I have a cli script running that use the filesize function on a ssh2_sftp connection. It has the >2Gb limit issue, while it does not have that issue locally. I have managed to get around this by doing a "du -sb" command through ssh2_shell.

The following function takes the ssh2_connect resource and the path as input. It may not be neat, but it solves the problem for the moment.

<?php
function fSSHFileSize($oConn, $sPath) {
    if(
false !== ($oShell = @ssh2_shell($oConn, 'xterm', null, 500, 24, SSH2_TERM_UNIT_CHARS))) {
       
fwrite($oShell, "du -sb '".$sPath."'".PHP_EOL);
       
sleep(1);
        while(
$sLine = fgets($oShell)) {
           
flush();
           
$aResult[] = $sLine;
        }
       
fclose($oShell);
       
$iSize = 0;
        if(
count($aResult) > 1) {
           
$sTemp = $aResult[count($aResult)-2];
           
$sSize = substr($sTemp, 0, strpos($sTemp, chr(9)));
            if(
is_numeric(trim($sSize))) {
               
$iTemp = (int)$sSize;
                if(
$iTemp > "2000000000") $iSize = $iTemp;
            }
        }
        return
$iSize;
    }
    return
0;
}
?>

jasondblount (at gmail) (15-Oct-2010 04:41)

Find filesize of any file ( >2GB works fine )

<?php
function ffilesize($file){
   
$ch = curl_init($file);
   
curl_setopt($ch, CURLOPT_NOBODY, true);
   
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   
curl_setopt($ch, CURLOPT_HEADER, true);
   
$data = curl_exec($ch);
   
curl_close($ch);
    if (
$data === false)
      return
false;
    if (
preg_match('/Content-Length: (\d+)/', $data, $matches))
      return (float)
$matches[1];
}
?>

joaoptm78 at gmail dot com (24-Sep-2010 07:26)

And this is my short and very clever simple function. Faster than some of the examples below.

<?php

function format_bytes($size) {
   
$units = array(' B', ' KB', ' MB', ' GB', ' TB');
    for (
$i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
    return
round($size, 2).$units[$i];
}

?>

You can add more units to the $units array and change the number 4 in "$i < 4" accordingly.

But if you want it really fast try this not-so-neat function:

<?php

function format_bytes($bytes) {
   if (
$bytes < 1024) return $bytes.' B';
   elseif (
$bytes < 1048576) return round($bytes / 1024, 2).' KB';
   elseif (
$bytes < 1073741824) return round($bytes / 1048576, 2).' MB';
   elseif (
$bytes < 1099511627776) return round($bytes / 1073741824, 2).' GB';
   else return
round($bytes / 1099511627776, 2).' TB';
}

?>

I guess you can do it in 1000 different ways :)

eric heudiard (11-Aug-2010 03:37)

It's very interesting but I can't stand the decimals for bytes and KB so here's another example :

<?php
function format_size($size) {
     
$sizes = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
      if (
$size == 0) { return('n/a'); } else {
      return (
round($size/pow(1024, ($i = floor(log($size, 1024)))), $i > 1 ? 2 : 0) . $sizes[$i]); }
}
?>

biolanor at googlemail dot com (20-Jul-2010 01:49)

This is a short and very clever function to get filesizes.

<?php
function format_size($size) {
     
$sizes = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
      if (
$size == 0) { return('n/a'); } else {
      return (
round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $sizes[$i]); }
}
?>

martinjohn dot sweeny at gmail dot com (17-Jun-2010 09:12)

Here is a quick function for getting a nicer filesize from a number:

<?php

function formatBytes($b,$p = null) {
   
/**
     *
     * @author Martin Sweeny
     * @version 2010.0617
     *
     * returns formatted number of bytes.
     * two parameters: the bytes and the precision (optional).
     * if no precision is set, function will determine clean
     * result automatically.
     *
     **/
   
$units = array("B","kB","MB","GB","TB","PB","EB","ZB","YB");
   
$c=0;
    if(!
$p && $p !== 0) {
        foreach(
$units as $k => $u) {
            if((
$b / pow(1024,$k)) >= 1) {
               
$r["bytes"] = $b / pow(1024,$k);
               
$r["units"] = $u;
               
$c++;
            }
        }
        return
number_format($r["bytes"],2) . " " . $r["units"];
    } else {
        return
number_format($b / pow(1024,$p)) . " " . $units[$p];
    }
}

echo
formatBytes(81000000);   //returns 77.25 MB
echo formatBytes(81000000,0); //returns 81,000,000 B
echo formatBytes(81000000,1); //returns 79,102 kB

?>

Feel free to email me if you can think of improvements!

jbudpro at comcast dot net (19-Apr-2010 11:58)

Get a real filesize value, return as a string, this way it will not have the same effect as filesize() returning an integer that will be limited by 32-bit php systems. Return can be cast to a (float) to work perfectly for files over 2GB
<?php
// WINDOWS SERVERS:
// str ntfs_filesize( str $filename );
/*
DESCRIPTION: returns the filesize of a large file in string format to...
... prevent 32-bit integer walls using windows command line.
*/
function ntfs_filesize($filename)
{
    return
exec("
            for %v in (\""
.$filename."\") do @echo %~zv
    "
);
}
// LINUX SERVERS:
// str perl_filesize( str $filename );
/*
DESCRIPTION: returns the filesize of a large file in string format to...
... prevent 32-bit integer walls  using perl through linux command line.
*/
function perl_filesize($filename)
{
    return
exec("
            perl -e 'printf \"%d\n\",(stat(shift))[7];' "
.$filename."
    "
);
}

// WARNING: For files over 2GB casting integers may give false values, to prevent this cast to a (float):

$file = "C:/my6GBmovie.avi"; // proper filesize: 6442450944 bytes
var_dump(ntfs_filesize($file); // output: string(10) "6442450944"
var_dump((int)ntfs_filesize($file)); // output: int(2147483647)
var_dump((float)ntfs_filesize($file)); // output: float(6442450944)

?>

itsrool at gmail dot com (12-Nov-2009 08:36)

My solution for calculating the directory size:

<?php
/**
 * Get the directory size
 * @param directory $directory
 * @return integer
 */
function dirSize($directory) {
   
$size = 0;
    foreach(new
RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file){
       
$size+=$file->getSize();
    }
    return
$size;
}
?>

tmont (25-Jul-2009 10:05)

Here's the best way (that I've found) to get the size of a remote file. Note that HEAD requests don't get the actual body of the request, they just retrieve the headers. So making a HEAD request to a resource that is 100MB will take the same amount of time as a HEAD request to a resource that is 1KB.

<?php
$remoteFile
= 'http://us.php.net/get/php-5.2.10.tar.bz2/from/this/mirror';
$ch = curl_init($remoteFile);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch);
curl_close($ch);
if (
$data === false) {
  echo
'cURL failed';
  exit;
}

$contentLength = 'unknown';
$status = 'unknown';
if (
preg_match('/^HTTP\/1\.[01] (\d\d\d)/', $data, $matches)) {
 
$status = (int)$matches[1];
}
if (
preg_match('/Content-Length: (\d+)/', $data, $matches)) {
 
$contentLength = (int)$matches[1];
}

echo
'HTTP Status: ' . $status . "\n";
echo
'Content-Length: ' . $contentLength;
?>

Result:

HTTP Status: 302
Content-Length: 8808759

Svetoslav Marinov (23-Jul-2009 06:24)

This is an updated version of my previous filesize2bytes.
The return type now it's really an int.

<?php
/**
 * Converts human readable file size (e.g. 10 MB, 200.20 GB) into bytes.
 *
 * @param string $str
 * @return int the result is in bytes
 * @author Svetoslav Marinov
 * @author http://slavi.biz
 */
function filesize2bytes($str) {
   
$bytes = 0;

   
$bytes_array = array(
       
'B' => 1,
       
'KB' => 1024,
       
'MB' => 1024 * 1024,
       
'GB' => 1024 * 1024 * 1024,
       
'TB' => 1024 * 1024 * 1024 * 1024,
       
'PB' => 1024 * 1024 * 1024 * 1024 * 1024,
    );

   
$bytes = floatval($str);

    if (
preg_match('#([KMGTP]?B)$#si', $str, $matches) && !empty($bytes_array[$matches[1]])) {
       
$bytes *= $bytes_array[$matches[1]];
    }

   
$bytes = intval(round($bytes, 2));

    return
$bytes;
}
?>

nak5ive at DONT-SPAM-ME dot gmail dot com (11-Jun-2009 06:59)

a quick way to convert bytes to a more readable format can be done using this function:

<?php
function formatBytes($bytes, $precision = 2) {
   
$units = array('B', 'KB', 'MB', 'GB', 'TB');
  
   
$bytes = max($bytes, 0);
   
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
   
$pow = min($pow, count($units) - 1);
  
   
$bytes /= pow(1024, $pow);
  
    return
round($bytes, $precision) . ' ' . $units[$pow];
}
?>

Anonymous (16-May-2009 10:49)

Shortest solution to get filesize of a remote website

<?php

$content
= file_get_contents("http://www.example.com");

$handle = fopen("example-com.html", "w+");

fwrite($handle, $content);

fclose($handle);

echo
size . ': ' . filesize('example-com.html') . ' bytes';

?>

hedora at web dot de (07-Feb-2009 02:23)

reliably, quick & dirty:

<?php
function getdirsize($path)
    {
   
$result=explode("\t",exec("du -hs ".$path),2);
    return (
$result[1]==$path ? $result[0] : "error");
    }
?>

bs_hck at bk dot ru (27-Jan-2009 07:06)

Fix 4Gb limit. ( Now limit 8 Gb ;))

<?php
   
function GetRealSize($file) {
       
// Return size in Mb
       
clearstatcache();
       
$INT = 4294967295;//2147483647+2147483647+1;
       
$size = filesize($file);
       
$fp = fopen($file, 'r');
       
fseek($fp, 0, SEEK_END);
        if (
ftell($fp)==0) $size += $INT;
       
fclose($file);
        if (
$size<0) $size += $INT;
        return
ceil($size/1024/1024);
    }
?>

7r6ivyeo at mail dot com (22-Nov-2008 01:36)

I use the CLI version of PHP on Windows Vista and work with large (~ 10G) Virtual Machine files.  Here's how to get a NTFS file's size without the 4G limit:

<?php
function dos_filesize($fn) {

    if (
is_file($fn))
        return
exec('FOR %A IN ("'.$fn.'") DO @ECHO %~zA');
    else
        return
'0';
}
?>

This should work on any Windows OS that provides DOS shell commands.

revoke (16-Sep-2008 10:23)

Another way for remote files -> strlen(join('',file('http://www.example.com/)));

Supermagnus (30-Jun-2008 11:38)

<?php
function getSizeFile($url) {
    if (
substr($url,0,4)=='http') {
       
$x = array_change_key_case(get_headers($url, 1),CASE_LOWER);
        if (
strcasecmp($x[0], 'HTTP/1.1 200 OK') != 0 ) { $x = $x['content-length'][1]; }
        else {
$x = $x['content-length']; }
    }
    else {
$x = @filesize($url); }

    return
$x;
}
?>

In case of you have a redirection in the server (like Redirect Permanent in the .htaccess)

In this case we have for exemple:
    [content-length] => Array

        (

            [0] => 294          // Size requested file

            [1] => 357556     // Real Size redirected file

        )

ronnie at logicalt dot com (03-Mar-2008 02:02)

Another workaround for the >2GB "stat failed" in Linux is to call the systems stat as follows:

$size = exec ('stat -c %s '. escapeshellarg ($file_path));

jason dot whitehead dot tas at gmail dot com (08-Feb-2008 11:14)

I have created a handy function, using parts of code from kaspernj at gmail dot com and md2perpe at gmail dot com, which should get file sizes > 4GB on Windows, Linux and Mac  (at least).

<?php
   
function getSize($file) {
       
$size = filesize($file);
        if (
$size < 0)
            if (!(
strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'))
               
$size = trim(`stat -c%s $file`);
            else{
               
$fsobj = new COM("Scripting.FileSystemObject");
               
$f = $fsobj->GetFile($file);
               
$size = $file->Size;
            }
        return
$size;
    }
?>

webmaster at eclipse org (07-Nov-2007 03:30)

On 64-bit platforms, this seems quite reliable for getting the filesize of files > 4GB

<?php
$a
= fopen($filename, 'r');
fseek($a, 0, SEEK_END);
$filesize = ftell($a);
fclose($a);
?>

MagicalTux at gmail dot com (16-Oct-2007 06:58)

filesize() acts differently between platforms and distributions.

I tried manually compiling PHP on a 32bit platform. Filesize() would fail on files >2G.

Then I compiled again, adding CFLAGS=`getconf LFS_CFLAGS` in front of configure.

Then filesize() would success, but the result would be converted to a 32bit signed integer...

However on 64bit systems, PHP's integers are 64bit signed, and this would work just well...

So now the question is : should linux distributions (Debian, etc) define LFS_CFLAGS or not ? Doing so makes PHP be able to open/seek such files, but makes its behaviour buggy (stat() is supposed to fail if file size is >32bit and appl does not support such integers)...

md2perpe at gmail dot com (17-Jul-2007 10:29)

Another way to get a filesize > 2GB on Linux:
<?php
$size
= trim(`stat -c%s $file_path`);
?>

Robin Leffmann (26-Jun-2007 01:49)

Here's a dodgy little snippet I made to find out how much disk space (in 1K-blocks) any chosen node - file or directory - occupies in the file system..

<?php
function nodesize( $node )
{
    if( !
is_readable($node) ) return false;
   
$blah = exec( "/usr/bin/du -sk $node" );
    return
substr( $blah, 0, strpos($blah, 9) );
}
?>

The character I search for with strpos() is a tab, as this is what 'du' on OpenBSD uses to separate size and node in the output - this might be whitespaces in other *nixes/distributions.

Josh Finlay <josh at glamourcastle dot com> (12-Nov-2006 08:22)

I know there has been alot of remote filesize snippets posted, but I'll post mine also.

It supports HTTP/HTTPS/FTP/FTPS and detects which type it should use. It needs --enable-ftp for the FTP/FTPS functions.

I hope this works for someone.

<?php
   
function remotefsize($url) {
       
$sch = parse_url($url, PHP_URL_SCHEME);
        if ((
$sch != "http") && ($sch != "https") && ($sch != "ftp") && ($sch != "ftps")) {
            return
false;
        }
        if ((
$sch == "http") || ($sch == "https")) {
           
$headers = get_headers($url, 1);
            if ((!
array_key_exists("Content-Length", $headers))) { return false; }
            return
$headers["Content-Length"];
        }
        if ((
$sch == "ftp") || ($sch == "ftps")) {
           
$server = parse_url($url, PHP_URL_HOST);
           
$port = parse_url($url, PHP_URL_PORT);
           
$path = parse_url($url, PHP_URL_PATH);
           
$user = parse_url($url, PHP_URL_USER);
           
$pass = parse_url($url, PHP_URL_PASS);
            if ((!
$server) || (!$path)) { return false; }
            if (!
$port) { $port = 21; }
            if (!
$user) { $user = "anonymous"; }
            if (!
$pass) { $pass = "phpos@"; }
            switch (
$sch) {
                case
"ftp":
                   
$ftpid = ftp_connect($server, $port);
                    break;
                case
"ftps":
                   
$ftpid = ftp_ssl_connect($server, $port);
                    break;
            }
            if (!
$ftpid) { return false; }
           
$login = ftp_login($ftpid, $user, $pass);
            if (!
$login) { return false; }
           
$ftpsize = ftp_size($ftpid, $path);
           
ftp_close($ftpid);
            if (
$ftpsize == -1) { return false; }
            return
$ftpsize;
        }
    }
?>

rico at ws5 dot org (08-Aug-2006 08:41)

To get the size of files above 2GB you can use the linux-command filesize like this:

<?php
   
function real_filesize_linux($file) {
        @
exec("filesize $file",$out,$ret);
        if (
$ret <> '0' ) return FALSE;
        else return(
$out[0]);
    }
?>

kaspernj at gmail dot com (18-Jul-2006 02:43)

If you want to get the actual filesize for a size above 2 gb in Windows, you can use the COM-extensions in PHP.

An example is as follows:

<?php
   
function knj_filesize($file){
        if (
file_exists($file)){
           
$fsobj = new COM("Scripting.FileSystemObject");
           
$file = $fsobj->GetFile($file);
           
$var = ($file->Size) + 1 - 1;
           
            return
$var;
        }else{
            echo
"File does not exist.\n";
            return
false;
        }
    }
?>

This will return the corrent filesize. And it is very useful with PHP-GTK applications, where you want to use the filesize for larger files.

This example also works for files over a Windows-network. Try this example with the function:

<?php
  
echo knj_filesize("//mycomputer/music/Track1.mp3");
?>

Happy hacking :)

core58 at mail dot ru (14-Apr-2006 04:21)

some notes and modifications to previous post.
refering to RFC, when using HTTP/1.1 your request (either GET or POST or HEAD) must contain Host header string, opposite to HTTP/1.1 where Host ain't required. but there's no sure how your remote server would treat the request so you can add Host anyway (it won't be an error for HTTP/1.0).
host value _must_ be a host name (not CNAME and not IP address).

this function catches response, containing Location header and recursively sends HEAD request to host where we are moved until final response is met.
(you can experience such redirections often when downloading something from php scripts or some hash links that use apache mod_rewrite. most all of dowloading masters handle 302 redirects correctly, so this code does it too (running recursively thru 302 redirections).)

[$counter302] specify how much times your allow this function to jump if redirections are met. If initial limit (5 is default) expired -- it returns 0 (should be modified for your purposes whatever).0
ReadHeader() function is listed in previous post
(param description is placed there too).

<?php
function remote_filesize_thru( $ipAddress, $url, $counter302 = 5 )
{
   
$socket = fsockopen( "10.233.225.2", 8080 );
    if( !
$socket )
    {
       
// failed to open TCP socket connection
        // do something sensible here besides exit();
       
echo "<br>failed to open socket for [$ipAddress]";
        exit();
    }
                   
   
// just send HEAD request to server
   
$head = "HEAD $url HTTP/1.0\r\nConnection: Close\r\n\r\n";
   
// you may use HTTP/1.1 instead, then your request head string _must_ contain "Host: " header
   
fwrite( $socket, $head );
       
   
// read the response header
   
$header = ReadHeader( $socket );
    if( !
$header )
    {
       
// handle empty response here the way you need...
       
Header( "HTTP/1.1 404 Not Found" );
        exit();
    }
   
   
fclose( $socket );
   
   
// check for "Location" header
   
$locationMarker = "Location: ";
   
$pos = strpos( $header, $locationMarker );
    if(
$pos > 0 )
    {
           
$counter302--;
            if(
$counter302 < 0 )
            {
                    
// redirect limit (5 by default) expired -- return some warning or do something sensible here
                   
echo "warning: too long redirection sequence";
                    return
0;
            }

           
// Location is present -- we should determine target host and move there, like any downloading masters do...
            // no need to use regex here
           
$end = strpos( $header, "\n", $pos );
           
$location = trim( substr( $header, $pos + strlen( $locationMarker ), $end - $pos - strlen( $locationMarker ) ), "\\r\\n" );
            
            
// extract pure host (without "http://")
            
$host = explode( "/", $location );
            
$ipa = gethostbyname( $host[2] );
            
// move to Location
            
return remote_filesize_thru( $ipa, $location, $counter302 );
    }
       
   
// try to acquire Content-Length within the response
   
$regex = '/Content-Length:\s([0-9].+?)\s/';
   
$count = preg_match($regex, $header, $matches);
                       
   
// if there was a Content-Length field, its value
    // will now be in $matches[1]
   
if( isset( $matches[1] ) )
         
$size = $matches[1];
    else
         
$size = 0;
   
    return
$size;
}
?>

core58 at mail dot ru (10-Apr-2006 01:09)

this is "raw" version of remote_filesize() function.
according to RFC, HTTP servers MUST implement at least GET, POST and HEAD requests, so the function just opens TCP socket connection, sends HEAD request and receives response, parsing length of the resource.
[$ipAddress] is the ip address of remote server.
[$url] is the name of file which size you want to determine.

the code was tested under Apache 2.0.43 and IIS 6.0 and it works correctly in both cases.
i wish the code can save someone's time :)

example:
$ipa = gethostbyname( "www.someserver.com" );
$url = "/docs/somedocument.pdf";

$fsize = remote_filesize2( $ipa, $url );

==========================

<?php

function ReadHeader( $socket )
{
   
$i=0;
   
$header = "";
    while(
true && $i<20 )
    {
       
// counter [$i] is used here to avoid deadlock while reading header string
        // it's limited by [20] here cause i really haven't ever met headers with string counter greater than 20
        // *
       
$s = fgets( $socket, 4096 );
       
$header .= $s;

        if(
strcmp( $s, "\r\n" ) == 0 || strcmp( $s, "\n" ) == 0 )
            break;
       
$i++;
    }
    if(
$i >= 20 )
    {
       
// suspicious header strings count was read
        // *
       
return false;
    }

    return
$header;
}

function
remote_filesize2( $ipAddress, $url )
{
   
$socket = fsockopen( $ipAddress, 80 );
    if( !
$socket )
    {
       
// failed to open TCP socket connection
        // do something sensible here besides exit();
        // ...
       
exit();
       
    }

   
// just send HEAD request to server
    // *
   
fwrite( $socket, "HEAD $url HTTP/1.0\r\nConnection: Close\r\n\r\n" );
   
   
// read the response header
    // *
   
$header = ReadHeader( $socket );
    if( !
$header )
    {
       
Header( "HTTP/1.1 404 Not Found" );
        exit();
    }

   
// try to acquire Content-Length within the response
    // *
   
$regex = '/Content-Length:\s([0-9].+?)\s/';
   
$count = preg_match($regex, $header, $matches);
  
   
// if there was a Content-Length field, its value
    // will now be in $matches[1]
   
if( isset( $matches[1] ) )
    {
       
$size = $matches[1];
    }
    else
    {
       
$size = 0;
    }
  
   
fclose( $socket );
    return
$size;

}
?>

mkamerma at science dot uva dot nl (12-Mar-2006 02:12)

When read/writing binary files you often cannot rely on the feof() function being of much use, since it doesn't get triggered if the pointer is at the eof but hasn't tried to read one more byte. In this case you instead need to check if the file pointer is at filesize yet, but if you don't have the filename handy, you need to pluck it out fstat all the time. Two simple functions that would be nice to have natively in PHP:

<?php
   
function fpfilesize(&$fp) { $stat = fstat($fp); return $stat["size"]; }

    function
fpeof(&$fp) { return ftell($fp)==fpfilesize($fp); }
?>

aidan at php dot net (13-Jul-2005 05:01)

This function quickly calculates the size of a directory:
http://aidanlister.com/repos/v/function.dirsize.php

You can convert filesizes to a human readable size using:
http://aidanlister.com/repos/v/function.size_readable.php

For a faster (unix only) implementation, see function.disk-total-space, note #34100
http://www.php.net/manual/en/function.disk-total-space.php#34100

Also of interest is this wikipedia article, discussing the difference between a kilobyte (1000) and a kibibyte (1024).
http://en.wikipedia.org/wiki/Bytes

bkimble at ebaseweb dot com (19-Nov-2004 11:33)

In addition to the handy function Kris posted, here is an upgraded version that does basic http authentication as well.

<?php
/*
* (mixed)remote_filesize($uri,$user='',$pw='')
* returns the size of a remote stream in bytes or
* the string 'unknown'. Also takes user and pw
* incase the site requires authentication to access
* the uri
*/
function remote_filesize($uri,$user='',$pw='')
{
   
// start output buffering
   
ob_start();
   
// initialize curl with given uri
   
$ch = curl_init($uri);
   
// make sure we get the header
   
curl_setopt($ch, CURLOPT_HEADER, 1);
   
// make it a http HEAD request
   
curl_setopt($ch, CURLOPT_NOBODY, 1);
   
// if auth is needed, do it here
   
if (!empty($user) && !empty($pw))
    {
       
$headers = array('Authorization: Basic ' base64_encode($user.':'.$pw)); 
       
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
   
$okay = curl_exec($ch);
   
curl_close($ch);
   
// get the output buffer
   
$head = ob_get_contents();
   
// clean the output buffer and return to previous
    // buffer settings
   
ob_end_clean();
   
   
// gets you the numeric value from the Content-Length
    // field in the http header
   
$regex = '/Content-Length:\s([0-9].+?)\s/';
   
$count = preg_match($regex, $head, $matches);
   
   
// if there was a Content-Length field, its value
    // will now be in $matches[1]
   
if (isset($matches[1]))
    {
       
$size = $matches[1];
    }
    else
    {
       
$size = 'unknown';
    }
   
    return
$size;
}
?>