filesize

(PHP 3, PHP 4, PHP 5)

filesize -- 取得文件大小

说明

int filesize ( string filename )

返回文件大小的字节数,如果出错返回 FALSE (在错误报告级别为 E_WARNING的情况下)。

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

注: 本函数的结果会被缓存。更多信息参见 clearstatcache()

提示: PHP 5.0.0 起本函数也可被某些 URL wrapper 使用。参考附录 L 来看哪些 wrapper 支持 stat() 系列函数的功能。

例子 1. filesize() 例子

<?php

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

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

?>

参见 file_exists()


add a note add a note User Contributed Notes
ming
04-Sep-2006 05:25
the "remote file size" snippet below is cool but only works in php5 since get_headers() is not supported in php4.
9U
25-Aug-2006 06:12
################################################
# Remote file size
$filename = 'http://www.url.com/image.jpg';
$ary_header = get_headers($filename, 1);       
          
$filesize = $ary_header['Content-Length'];
$type = $ary_header['Content-Type'];
g8z at yahoo dot com
15-Aug-2006 03:48
<?php
/**
Here is a CURL version of the remote_filesize function,
which also supports http authentication if required.

Courtesy of the $5 Script Archive: http://www.tufat.com
**/

// EXAMPLE:

echo remote_filesize("http://download.tufat.com/test.zip","","");

function
remote_filesize($url, $user = "", $pw = "") {
  
ob_start();
  
$ch = curl_init($url);
  
curl_setopt($ch, CURLOPT_HEADER, 1);
  
curl_setopt($ch, CURLOPT_NOBODY, 1);
   if(!empty(
$user) && !empty($pw)) {
      
$headers = array('Authorization: Basic ' . base64_encode("$user:$pw"));
      
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
   }
  
$ok = curl_exec($ch);
  
curl_close($ch);
  
$head = ob_get_contents();
  
ob_end_clean();
  
$regex = '/Content-Length:\s([0-9].+?)\s/';
  
$count = preg_match($regex, $head, $matches);

   return isset(
$matches[1]) ? $matches[1] : "unknown";
}
?>
rico at ws5 dot org
08-Aug-2006 03: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 09: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:

<?
  
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:

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

Happy hacking :)
core58 at mail dot ru
14-Apr-2006 11: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;
}
fabio at nospam dot please dot nitrodev dot com
13-Apr-2006 08:46
core58 at mail dot ru, it did save me time!

One note though. I had to add the Host: header in order to get it working. The value should be the host name (DNS, not IP).
php dot net at alan-smith dot no-ip dot com
13-Apr-2006 06:16
<?
function size_hum_read($size){
/*
Returns a human readable size
*/
 
$i=0;
 
$iec = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
  while ((
$size/1024)>1) {
  
$size=$size/1024;
  
$i++;
  }
  return
substr($size,0,strpos($size,'.')+4).$iec[$i];
}
// Usage : size_hum_read(filesize($file));
?>
core58 at mail dot ru
10-Apr-2006 08: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 10: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); }
?>
Jonas Sweden
10-Mar-2006 08:55
<?php

/* Recursive filesize, nothing new but a small one.
The $self var as a convenience if i want to change
functionname */

function filesize_r($path){
if(!
file_exists($path)) return 0;
if(
is_file($path)) return filesize($path);
$self = __FUNCTION__;
$ret = 0;
foreach(
glob($path."/*") as $fn)
$ret += $self($fn);
return
$ret;
}

?>
jiquera at yahoo dot com
07-Mar-2006 12:02
here a piece of code to format a filesize:

<?php

function    formatbytes($val, $digits = 3, $mode = "SI", $bB = "B"){ //$mode == "SI"|"IEC", $bB == "b"|"B"
      
$si = array("", "k", "M", "G", "T", "P", "E", "Z", "Y");
      
$iec = array("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi");
       switch(
strtoupper($mode)) {
           case
"SI" : $factor = 1000; $symbols = $si; break;
           case
"IEC" : $factor = 1024; $symbols = $iec; break;
           default :
$factor = 1000; $symbols = $si; break;
       }
       switch(
$bB) {
           case
"b" : $val *= 8; break;
           default :
$bB = "B"; break;
       }
       for(
$i=0;$i<count($symbols)-1 && $val>=$factor;$i++)
          
$val /= $factor;
      
$p = strpos($val, ".");
       if(
$p !== false && $p > $digits) $val = round($val);
       elseif(
$p !== false) $val = round($val, $digits-$p);
       return
round($val, $digits) . " " . $symbols[$i] . $bB;
   }

//some test cases:

  
function test($i, $digits = 3, $mode = "SI", $bB = "B"){
       echo
$i . " = " . formatbytes($i, $digits, $mode, $bB) . "<br>\n";   
   }
  
  
test(1024);
  
test(1024*1024);
  
test(1024*1024, 4);
  
test(1024*1024, 3, "IEC");
  
test(1024, 3, "SI", "b");
  
test(32423);
  
test(323);
  
test(128, "3", "IEC", "b");
  
test(324235236362453);
  
test(32423535424236324362453, 3, "IEC");

//actual use:

echo formatbytes(file_size("myfile.php"));

?>

it formats to bit or bytes according to SI or IEC and rounded to a given number of digits.
RobKohrPhp at remail dot robkohr dot com
05-Feb-2006 04:42
Simplified recursive size measurement. Will also take into account the size of the folders themselves.
 
function get_size($path)
   {
       if(!is_dir($path)) return filesize($path);
   if ($handle = opendir($path)) {
       $size = 0;
       while (false !== ($file = readdir($handle))) {
           if($file!='.' && $file!='..'){
                   $size += filesize($path.'/'.$file);
               $size += get_size($path.'/'.$file);
           }
       }
       closedir($handle);
       return $size;
   }
}
will at imarc dot net
29-Jan-2006 08:08
If you are trying to find a way to get the filesize for files over 2GB, you can always use exec() and run a system command to return the value. The following works on my linux box:

$sizeInBytes = filesize($path);
if (!$sizeInBytes) {
   $command = "ls -l \"$path\" | cut -d \" \" -f 6";
   $sizeInBytes = exec($command);       
}
mateusz at bsdmail dot org
01-Jan-2006 02:54
Recursive function, which returns size of folder or file.
<?php
function get_size($path)
   {
       if(!
is_dir($path))return filesize($path);
      
$dir = opendir($path);
       while(
$file = readdir($dir))
       {
           if(
is_file($path."/".$file))$size+=filesize($path."/".$file);
           if(
is_dir($path."/".$file) && $file!="." && $file !="..")$size +=get_size($path."/".$file);
          
       }
       return
$size;
   }
?>
aidan at php dot net
13-Jul-2005 12:01
This function uses a stack array to get the size of a directory.
http://aidan.dotgeek.org/lib/?file=function.dirsize.php

You can convert this 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
Raphael Kirchner
06-Mar-2005 10:52
Addition to my earlier post: I searched around and found the background in the notes for disk_total_space():  http://www.php.net/manual/en/function.disk-total-space.php
To give a short summary here - andudi pointed out that
a) the SIZE of a file and
b) the SPACE on disk it uses
aren't equal and shalless provided a function dskspace() which returns exactly (tested!) what "du" would.
bkimble at ebaseweb dot com
20-Nov-2004 07: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;
}
?>