rapido - PHP x86 ¿Cómo obtener tamaño de archivo de> 2 GB sin programa externo?
enviar archivos pesados rapido (14)
Necesito obtener el tamaño de archivo de un archivo de más de 2 GB de tamaño. (prueba en un archivo de 4.6 GB). ¿Hay alguna manera de hacer esto sin un programa externo?
Estado actual:
-
filesize()
,stat()
yfseek()
fallan -
fread()
yfeof()
funciona
Existe la posibilidad de obtener el tamaño del archivo leyendo el contenido del archivo (¡extremadamente lento!).
$size = (float) 0;
$chunksize = 1024 * 1024;
while (!feof($fp)) {
fread($fp, $chunksize);
$size += (float) $chunksize;
}
return $size;
Sé cómo obtenerlo en plataformas de 64 bits (usando fseek($fp, 0, SEEK_END)
y ftell()
), pero necesito una solución para la plataforma de 32 bits.
Solución: comencé un proyecto de código abierto para esto.
Big File Tools
Big File Tools es una colección de hacks que se necesitan para manipular archivos de más de 2 GB en PHP (incluso en sistemas de 32 bits).
- respuesta: https://stackoverflow.com/a/35233556/631369
- github: https://github.com/jkuchar/BigFileTools
Aquí hay un posible método:
Primero intenta usar un comando de shell apropiado para la plataforma (modificadores de sustitución del shell de Windows o el comando * nix / Mac stat
). Si eso falla, intenta COM (si está en Windows) y finalmente vuelve a 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);
}
Cuando se usa IEEE doble (la mayoría de los sistemas), los tamaños de archivo inferiores a ~ 4EB (etabytes = 10 ^ 18 bytes) se ajustan al doble como números precisos (y no debe haber pérdida de precisión cuando se usan operaciones aritméticas estándar).
El código siguiente funciona bien para cualquier tamaño de archivo en cualquier versión de 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
Empecé un proyecto llamado https://github.com/jkuchar/BigFileTools . Está proven que funciona en Linux, Mac y Windows (incluso en variantes de 32 bits). Proporciona resultados precisos por bytes incluso para archivos de gran tamaño (> 4 GB). Internamente usa brick/math - biblioteca aritmética de precisión arbitraria.
Instálalo usando el composer .
composer install jkuchar/BigFileTools
y úsala:
<?php
$file = BigFileTools/BigFileTools::createDefault()->getFile(__FILE__);
echo $file->getSize() . " bytes/n";
El resultado es BigInteger para que pueda calcular con los resultados
$sizeInBytes = $file->getSize();
$sizeInMegabytes = $sizeInBytes->toBigDecimal()->dividedBy(1024*1024, 2, /Brick/Math/RoundingMode::HALF_DOWN);
echo "Size is $sizeInMegabytes megabytes/n";
Big File Tools internamente utiliza controladores para determinar de manera confiable el tamaño exacto del archivo en todas las plataformas. Aquí está la lista de controladores disponibles (actualizado el 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 | - | -
Puede utilizar BigFileTools con cualquiera de estos o el más rápido disponible se elige de forma predeterminada ( BigFileTools::createDefault()
)
use BigFileTools/BigFileTools;
use BigFileTools/Driver;
$bigFileTools = new BigFileTools(new Driver/CurlDriver());
Encontré una buena solución delgada para Linux / Unix solo para obtener el tamaño de archivo de archivos grandes con php de 32 bits.
$file = "/path/to/my/file.tar.gz";
$filesize = exec("stat -c %s ".$file);
Debería manejar $filesize
como cadena. Intentar convertir como int resulta en un tamaño de archivo = PHP_INT_MAX si el tamaño del archivo es mayor que PHP_INT_MAX.
Pero aunque se maneja como una cadena, funciona el siguiente algoritmo legible por humanos:
formatBytes($filesize);
public function formatBytes($size, $precision = 2) {
$base = log($size) / log(1024);
$suffixes = array('''', ''k'', ''M'', ''G'', ''T'');
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
}
entonces mi salida para un archivo de más de 4 Gb es:
4.46G
Es posible que desee agregar algunas alternativas a la función que utiliza, como llamar a funciones del sistema como "dir" / "ls" y obtener la información desde allí. Por supuesto, están sujetos a seguridad, cosas que puedes verificar y, finalmente, volver al método lento solo como último recurso.
Escribí una función que devuelve el tamaño del archivo exactamente y es bastante rápido:
function file_get_size($file) {
//open file
$fh = fopen($file, "r");
//declare some variables
$size = "0";
$char = "";
//set file pointer to 0; I''m a little bit paranoid, you can remove this
fseek($fh, 0, SEEK_SET);
//set multiplicator to zero
$count = 0;
while (true) {
//jump 1 MB forward in file
fseek($fh, 1048576, SEEK_CUR);
//check if we actually left the file
if (($char = fgetc($fh)) !== false) {
//if not, go on
$count ++;
} else {
//else jump back where we were before leaving and exit loop
fseek($fh, -1048576, SEEK_CUR);
break;
}
}
//we could make $count jumps, so the file is at least $count * 1.000001 MB large
//1048577 because we jump 1 MB and fgetc goes 1 B forward too
$size = bcmul("1048577", $count);
//now count the last few bytes; they''re always less than 1048576 so it''s quite fast
$fine = 0;
while(false !== ($char = fgetc($fh))) {
$fine ++;
}
//and add them
$size = bcadd($size, $fine);
fclose($fh);
return $size;
}
La forma más fácil de hacer eso sería simplemente agregar un valor máximo a su número. Esto significa que en la plataforma x86, un número largo agrega 2 ^ 32:
if($size < 0) $size = pow(2,32) + $size;
ejemplo: Big_File.exe - 3,30Gb (3.554.287.616 b) su función devuelve -740679680 por lo que agrega 2 ^ 32 (4294967296) y obtiene 3554287616.
Obtiene un número negativo porque su sistema reserva un bit de memoria para el signo negativo, por lo que le quedan 2 ^ 31 (2.147.483.648 = 2G) valor máximo de número negativo o positivo. Cuando el sistema alcanza este valor máximo, no se detiene sino que simplemente sobrescribe el último bit reservado y su número ahora se fuerza a negativo. En palabras más simples, cuando exceda el número positivo máximo, se lo forzará a un número negativo máximo, por lo que 2147483648 + 1 = -2147483648. La adición adicional va hacia cero y de nuevo hacia el número máximo.
Como puede ver, es como un círculo con los números más altos y más bajos cerrando el ciclo.
El número máximo total que la arquitectura x86 puede "digerir" de una vez es 2 ^ 32 = 4294967296 = 4G, por lo que siempre que su número sea inferior a ese, este simple truco siempre funcionará. En números más altos, debes saber cuántas veces has pasado el punto de repetición y simplemente multiplicarlo por 2 ^ 32 y agregarlo a tu resultado:
$size = pow(2,32) * $loops_count + $size;
Por supuesto, en las funciones básicas de PHP esto es bastante difícil de hacer, porque ninguna función le dirá cuántas veces ha pasado el punto de repetición, por lo que esto no funcionará para los archivos de 4Gigs.
No se puede obtener de manera confiable el tamaño de un archivo en un sistema de 32 bits comprobando si filesize () arroja resultados negativos, como sugieren algunas respuestas. Esto se debe a que si un archivo tiene entre 4 y 6 gigas en un sistema de 32 bits, el tamaño del archivo indicará un número positivo, luego negativo de 6 a 8, luego positivo de 8 a 10, y así sucesivamente. Bucle, como una manera de hablar.
Entonces estás atrapado usando un comando externo que funciona de manera confiable en tu sistema de 32 bits.
Sin embargo, una herramienta muy útil es la capacidad de comprobar si el tamaño del archivo es mayor que un determinado tamaño y puede hacerlo de forma fiable incluso en archivos muy grandes.
Lo siguiente busca 50 megas e intenta leer un byte. Es muy rápido en mi máquina de prueba de baja especificación y funciona de manera confiable incluso cuando el tamaño es mucho mayor que 2 gigas.
Puede usar esto para verificar si un archivo es mayor que 2147483647 bytes (2147483648 es máximo int en sistemas de 32 bits) y luego manejar el archivo de manera diferente o hacer que su aplicación emita una advertencia.
function isTooBig($file){
$fh = @fopen($file, ''r'');
if(! $fh){ return false; }
$offset = 50 * 1024 * 1024; //50 megs
$tooBig = false;
if(fseek($fh, $offset, SEEK_SET) === 0){
if(strlen(fread($fh, 1)) === 1){
$tooBig = true;
}
} //Otherwise we couldn''t seek there so it must be smaller
fclose($fh);
return $tooBig;
}
Si tiene un servidor FTP, puede usar fsockopen:
$socket = fsockopen($hostName, 21);
$t = fgets($socket, 128);
fwrite($socket, "USER $myLogin/r/n");
$t = fgets($socket, 128);
fwrite($socket, "PASS $myPass/r/n");
$t = fgets($socket, 128);
fwrite($socket, "SIZE $fileName/r/n");
$t = fgets($socket, 128);
$fileSize=floatval(str_replace("213 ","",$t));
echo $fileSize;
fwrite($socket, "QUIT/r/n");
fclose($socket);
(Se encuentra como un comentario en la página ftp_size )
Una opción sería buscar la marca de 2 gb y luego leer la longitud desde allí ...
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;
}
Así que, básicamente, busca el entero con signo positivo más grande representable en PHP (2 gb para un sistema de 32 bits), y luego lee a partir de entonces utilizando bloques de 8 kb (lo que debería ser una compensación justa para la mejor eficiencia de memoria frente a la eficiencia de transferencia de disco).
También tenga en cuenta que no estoy agregando $chunksize
al tamaño. La razón es que fread
puede devolver más o menos bytes que $chunksize
dependiendo de una cantidad de posibilidades. Por lo tanto, use strlen
para determinar la longitud de la cadena analizada.
Repetí la clase / respuesta de BigFileTools :
-opción para deshabilitar el método curl porque algunas plataformas (Synology NAS por ejemplo) no son compatibles con el protocolo FTP para Curl
-extra non posix, pero más precisa, la implementación de sizeExec , en lugar de tamaño en el disco, el tamaño real del archivo se devuelve utilizando stat en lugar de du
- resultados de tamaño correcto para archivos grandes (> 4 GB) y casi tan rápido para sizeNativeSeek
-opción de mensajes de descarte
<?php
/**
* Class for manipulating files bigger than 2GB
* (currently supports only getting filesize)
*
* @author Honza Kuchař
* @license New BSD
* @encoding UTF-8
* @copyright Copyright (c) 2013, Jan Kuchař
*/
class BigFileTools {
/**
* Absolute file path
* @var string
*/
protected $path;
/**
* Use in BigFileTools::$mathLib if you want to use BCMath for mathematical operations
*/
const MATH_BCMATH = "BCMath";
/**
* Use in BigFileTools::$mathLib if you want to use GMP for mathematical operations
*/
const MATH_GMP = "GMP";
/**
* Which mathematical library use for mathematical operations
* @var string (on of constants BigFileTools::MATH_*)
*/
public static $mathLib;
/**
* If none of fast modes is available to compute filesize, BigFileTools uses to compute size very slow
* method - reading file from 0 byte to end. If you want to enable this behavior,
* switch fastMode to false (default is true)
* @var bool
*/
public static $fastMode = true;
//on some platforms like Synology NAS DS214+ DSM 5.1 FTP Protocol for curl is not working or disabled
// you will get an error like "Protocol file not supported or disabled in libcurl"
public static $FTPProtocolCurlEnabled = false;
public static $debug=false; //shows some debug/error messages
public static $posix=true; //more portable but it shows size on disk not actual filesize so it''s less accurate: 0..clustersize in bytes inaccuracy
/**
* Initialization of class
* Do not call directly.
*/
static function init() {
if (function_exists("bcadd")) {
self::$mathLib = self::MATH_BCMATH;
} elseif (function_exists("gmp_add")) {
self::$mathLib = self::MATH_GMP;
} else {
throw new BigFileToolsException("You have to install BCMath or GMP. There mathematical libraries are used for size computation.");
}
}
/**
* Create BigFileTools from $path
* @param string $path
* @return BigFileTools
*/
static function fromPath($path) {
return new self($path);
}
static function debug($msg) {
if (self::$debug) echo $msg;
}
/**
* Gets basename of file (example: for file.txt will return "file")
* @return string
*/
public function getBaseName() {
return pathinfo($this->path, PATHINFO_BASENAME);
}
/**
* Gets extension of file (example: for file.txt will return "txt")
* @return string
*/
public function getExtension() {
return pathinfo($this->path, PATHINFO_EXTENSION);
}
/**
* Gets extension of file (example: for file.txt will return "file.txt")
* @return string
*/
public function getFilename() {
return pathinfo($this->path, PATHINFO_FILENAME);
}
/**
* Gets path to file of file (example: for file.txt will return path to file.txt, e.g. /home/test/)
* ! This will call absolute path!
* @return string
*/
public function getDirname() {
return pathinfo($this->path, PATHINFO_DIRNAME);
}
/**
* Gets md5 checksum of file content
* @return string
*/
public function getMd5() {
return md5_file($this->path);
}
/**
* Gets sha1 checksum of file content
* @return string
*/
public function getSha1() {
return sha1_file($this->path);
}
/**
* Constructor - do not call directly
* @param string $path
*/
function __construct($path, $absolutizePath = true) {
if (!static::isReadableFile($path)) {
throw new BigFileToolsException("File not found at $path");
}
if($absolutizePath) {
$this->setPath($path);
}else{
$this->setAbsolutePath($path);
}
}
/**
* Tries to absolutize path and than updates instance state
* @param string $path
*/
function setPath($path) {
$this->setAbsolutePath(static::absolutizePath($path));
}
/**
* Setts absolute path
* @param string $path
*/
function setAbsolutePath($path) {
$this->path = $path;
}
/**
* Gets current filepath
* @return string
*/
function getPath($a = "") {
if(a != "") {
trigger_error("getPath with absolutizing argument is deprecated!", E_USER_DEPRECATED);
}
return $this->path;
}
/**
* Converts relative path to absolute
*/
static function absolutizePath($path) {
$path = realpath($path);
if(!$path) {
// TODO: use hack like http://.com/questions/4049856/replace-phps-realpath or http://www.php.net/manual/en/function.realpath.php#84012
// probaly as optinal feature that can be turned on when you know, what are you doing
throw new BigFileToolsException("Not possible to resolve absolute path.");
}
return $path;
}
static function isReadableFile($file) {
// Do not use is_file
// @link https://bugs.php.net/bug.php?id=27792
// $readable = is_readable($file); // does not always return correct value for directories
$fp = @fopen($file, "r"); // must be file and must be readable
if($fp) {
fclose($fp);
return true;
}
return false;
}
/**
* Moves file to new location / rename
* @param string $dest
*/
function move($dest) {
if (move_uploaded_file($this->path, $dest)) {
$this->setPath($dest);
return TRUE;
} else {
@unlink($dest); // needed in PHP < 5.3 & Windows; intentionally @
if (rename($this->path, $dest)) {
$this->setPath($dest);
return TRUE;
} else {
if (copy($this->path, $dest)) {
unlink($this->path); // delete file
$this->setPath($dest);
return TRUE;
}
return FALSE;
}
}
}
/**
* Changes path of this file object
* @param string $dest
*/
function relocate($dest) {
trigger_error("Relocate is deprecated!", E_USER_DEPRECATED);
$this->setPath($dest);
}
/**
* Size of file
*
* Profiling results:
* sizeCurl 0.00045299530029297
* sizeNativeSeek 0.00052094459533691
* sizeCom 0.0031449794769287
* sizeExec 0.042937040328979
* sizeNativeRead 2.7670161724091
*
* @return string | float
* @throws BigFileToolsException
*/
public function getSize($float = false) {
if ($float == true) {
return (float) $this->getSize(false);
}
$return = $this->sizeCurl();
if ($return) {
$this->debug("sizeCurl succeeded");
return $return;
}
$this->debug("sizeCurl failed");
$return = $this->sizeNativeSeek();
if ($return) {
$this->debug("sizeNativeSeek succeeded");
return $return;
}
$this->debug("sizeNativeSeek failed");
$return = $this->sizeCom();
if ($return) {
$this->debug("sizeCom succeeded");
return $return;
}
$this->debug("sizeCom failed");
$return = $this->sizeExec();
if ($return) {
$this->debug("sizeExec succeeded");
return $return;
}
$this->debug("sizeExec failed");
if (!self::$fastMode) {
$return = $this->sizeNativeRead();
if ($return) {
$this->debug("sizeNativeRead succeeded");
return $return;
}
$this->debug("sizeNativeRead failed");
}
throw new BigFileToolsException("Can not size of file $this->path !");
}
// <editor-fold defaultstate="collapsed" desc="size* implementations">
/**
* Returns file size by using native fseek function
* @see http://www.php.net/manual/en/function.filesize.php#79023
* @see http://www.php.net/manual/en/function.filesize.php#102135
* @return string | bool (false when fail)
*/
protected function sizeNativeSeek() {
$fp = fopen($this->path, "rb");
if (!$fp) {
return false;
}
flock($fp, LOCK_SH);
$result= fseek($fp, 0, SEEK_END);
if ($result===0) {
if (PHP_INT_SIZE < 8) {
// 32bit
$return = 0.0;
$step = 0x7FFFFFFF;
while ($step > 0) {
if (0 === fseek($fp, - $step, SEEK_CUR)) {
$return += floatval($step);
} else {
$step >>= 1;
}
}
}
else { //64bit
$return = ftell($fp);
}
}
else $return = false;
flock($fp, LOCK_UN);
fclose($fp);
return $return;
}
/**
* Returns file size by using native fread function
* @see http://.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5504829#5504829
* @return string | bool (false when fail)
*/
protected function sizeNativeRead() {
$fp = fopen($this->path, "rb");
if (!$fp) {
return false;
}
flock($fp, LOCK_SH);
rewind($fp);
$offset = PHP_INT_MAX - 1;
$size = (string) $offset;
if (fseek($fp, $offset) !== 0) {
flock($fp, LOCK_UN);
fclose($fp);
return false;
}
$chunksize = 1024 * 1024;
while (!feof($fp)) {
$read = strlen(fread($fp, $chunksize));
if (self::$mathLib == self::MATH_BCMATH) {
$size = bcadd($size, $read);
} elseif (self::$mathLib == self::MATH_GMP) {
$size = gmp_add($size, $read);
} else {
throw new BigFileToolsException("No mathematical library available");
}
}
if (self::$mathLib == self::MATH_GMP) {
$size = gmp_strval($size);
}
flock($fp, LOCK_UN);
fclose($fp);
return $size;
}
/**
* Returns file size using curl module
* @see http://www.php.net/manual/en/function.filesize.php#100434
* @return string | bool (false when fail or cUrl module not available)
*/
protected function sizeCurl() {
// curl solution - cross platform and really cool :)
if (self::$FTPProtocolCurlEnabled && function_exists("curl_init")) {
$ch = curl_init("file://" . $this->path);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$data = curl_exec($ch);
if ($data=="" || empty($data)) $this->debug(stripslashes(curl_error($ch)));
curl_close($ch);
if ($data !== false && preg_match(''/Content-Length: (/d+)/'', $data, $matches)) {
return (string) $matches[1];
}
} else {
return false;
}
}
/**
* Returns file size by using external program (exec needed)
* @see http://.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5502328#5502328
* @return string | bool (false when fail or exec is disabled)
*/
protected function sizeExec() {
// filesize using exec
if (function_exists("exec")) {
if (strtoupper(substr(PHP_OS, 0, 3)) == ''WIN'') { // Windows
// Try using the NT substition modifier %~z
$escapedPath = escapeshellarg($this->path);
$size = trim(exec("for %F in ($escapedPath) do @echo %~zF"));
}else{ // other OS
// If the platform is not Windows, use the stat command (should work for *nix and MacOS)
if (self::$posix) {
$tmpsize=trim(exec("du /"".$this->path."/" | cut -f1"));
//du returns blocks/KB
$size=(int)$tmpsize*1024; //make it bytes
}
else $size=trim(exec(''stat "''.$this->path.''" | grep -i -o -E "Size: ([0-9]+)" | cut -d" " -f2''));
if (self::$debug) var_dump($size);
return $size;
}
}
return false;
}
/**
* Returns file size by using Windows COM interface
* @see http://.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5502328#5502328
* @return string | bool (false when fail or COM not available)
*/
protected function sizeCom() {
if (class_exists("COM")) {
// Use the Windows COM interface
$fsobj = new COM(''Scripting.FileSystemObject'');
if (dirname($this->path) == ''.'')
$this->path = ((substr(getcwd(), -1) == DIRECTORY_SEPARATOR) ? getcwd() . basename($this->path) : getcwd() . DIRECTORY_SEPARATOR . basename($this->path));
$f = $fsobj->GetFile($this->path);
return (string) $f->Size;
}
}
// </editor-fold>
}
BigFileTools::init();
class BigFileToolsException extends Exception{}
$file_size=sprintf("%u",filesize($working_dir."//".$file));
Esto funciona para mí en un Windows Box.
Estaba mirando el registro de errores aquí: https://bugs.php.net/bug.php?id=63618 y encontré esta solución.
<?php
######################################################################
# Human size for files smaller or bigger than 2 GB on 32 bit Systems #
# size.php - 1.1 - 17.01.2012 - Alessandro Marinuzzi - www.alecos.it #
######################################################################
function showsize($file) {
if (strtoupper(substr(PHP_OS, 0, 3)) == ''WIN'') {
if (class_exists("COM")) {
$fsobj = new COM(''Scripting.FileSystemObject'');
$f = $fsobj->GetFile(realpath($file));
$file = $f->Size;
} else {
$file = trim(exec("for %F in (/"" . $file . "/") do @echo %~zF"));
}
} elseif (PHP_OS == ''Darwin'') {
$file = trim(shell_exec("stat -f %z " . escapeshellarg($file)));
} elseif ((PHP_OS == ''Linux'') || (PHP_OS == ''FreeBSD'') || (PHP_OS == ''Unix'') || (PHP_OS == ''SunOS'')) {
$file = trim(shell_exec("stat -c%s " . escapeshellarg($file)));
} else {
$file = filesize($file);
}
if ($file < 1024) {
echo $file . '' Byte'';
} elseif ($file < 1048576) {
echo round($file / 1024, 2) . '' KB'';
} elseif ($file < 1073741824) {
echo round($file / 1048576, 2) . '' MB'';
} elseif ($file < 1099511627776) {
echo round($file / 1073741824, 2) . '' GB'';
} elseif ($file < 1125899906842624) {
echo round($file / 1099511627776, 2) . '' TB'';
} elseif ($file < 1152921504606846976) {
echo round($file / 1125899906842624, 2) . '' PB'';
} elseif ($file < 1180591620717411303424) {
echo round($file / 1152921504606846976, 2) . '' EB'';
} elseif ($file < 1208925819614629174706176) {
echo round($file / 1180591620717411303424, 2) . '' ZB'';
} else {
echo round($file / 1208925819614629174706176, 2) . '' YB'';
}
}
?>
Use de la siguiente manera:
<?php include("php/size.php"); ?>
Y donde quieras:
<?php showsize("files/VeryBigFile.rar"); ?>
Si quieres mejorarlo, ¡eres bienvenido!