Reputation: 1371
I am writing an application that can stream videos. It requires the filesize of the video, so I use this code:
$filesize = sprintf("%u", filesize($file));
However, when streaming a six gig movie, it fails.
Is is possible to get a bigger interger value in PHP? I don't care if I have to use third party libraries, if it is slow, all I care about is that it can get the filesize properly.
FYI, $filesize
is currently 3017575487 which is really really really really far from 6000000000, which is roughly correct.
I am running PHP on a 64 bit operating system.
Thanks for any suggestions!
Upvotes: 0
Views: 109
Reputation: 60517
The issue here is two-fold.
The filesize
function returns a signed integer, with a maximum value of PHP_INT_MAX
. On 32-bit PHP, this value is 2147483647
or about 2GB. On 64-bit PHP can you go higher, up to 9223372036854775807
. Based on the comments from the PHP filesize
page, I created a function that will use a fseek
loop to find the size of the file, and return it as a float
, which can count higher that a 32-bit unisgned integer.
function filesize_float($filename)
{
$f = fopen($filename, 'r');
$p = 0;
$b = 1073741824;
fseek($f, 0, SEEK_SET);
while($b > 1)
{
fseek($f, $b, SEEK_CUR);
if(fgetc($f) === false)
{
fseek($f, -$b, SEEK_CUR);
$b = (int)($b / 2);
}
else
{
fseek($f, -1, SEEK_CUR);
$p += $b;
}
}
while(fgetc($f) !== false)
{
++$p;
}
fclose($f);
return $p;
}
To get the file size of the file as a float using the above function, you would call it like this.
$filesize = filesize_float($file);
Using %u
in the sprintf
function will cause it to interpret the argument as an unsigned integer, thus limiting the maximum possible value to 4294967295
on 32-bit PHP, before overflowing. Therefore, if we were to do the following, it would return the wrong number.
sprintf("%u", filesize_float($file));
You could interpret the value as a float using %F
, using the following, but it will result in trailing decimals.
sprintf("%F", filesize_float($file));
For example, the above will return something like 6442450944.000000
, rather than 6442450944
.
A workaround would be to have sprintf
interpret the float as a string, and let PHP cast the float to a string.
$filesize = sprintf("%s", filesize_float($file));
This will set $filesize
to the value of something like 6442450944
, without trailing decimals.
If you add the filesize_float
function above to your code, you can simply use the following line of code to read the actual file size into the sprintf
statement.
$filesize = sprintf("%s", filesize_float($file));
Upvotes: 1
Reputation: 5147
As per PHP docuemnation for 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);
?>
Upvotes: 0