PHP获取文件的大小

这个类可以判断文件的大小,即使大于2GB,它可以使用不同的方法来确定一个大的文件。

<?php
/**
 * ----------------------------------------------------------------------
 * FileSizeHelper
 * ----------------------------------------------------------------------
 *
 * Class for manipulating large files (bigger than 2GB)
 * 
 * This class detects the real file size of a specified file even if the 
 * file size is begger than 2GB, the class also able to format the resulted
 * file size in KB, MB, GB, TB units which make it more readable.
 * 
 *  The class uses several methods to detect bigger file sizes:
 *  1. The native filesize() function
 *  2. Using the cURL module
 *  3. Using the php native seek function
 *  4. Windows COM interface (on windows server)
 *  5. Using external program (exec() function needed)
 */
 
class FilesizeHelper {
 
    /**
     * File path
     *
     * @var     string
     * @access  private
     */
    private $path;
 
    /**
     * File size in bytes
     *
     * @var     float
     * @access  private
     */
    private $byteSize;
 
    /**
     * Whether we are on Windows platform or another OS (*nix and MacOS)
     *
     * @var     bool
     * @access  private
     */
    private $isWindows;
 
    /**
     * Constructor
     *
     * @access  public
     * @param   void
     * @return  void
     */
    public function __construct() {
 
        // Check if we are on Windows platform
        $this->isWindows = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
    }
 
    /**
     * Gets the size of the specified file
     *
     * @access  public
     * @param   string  The file path
     * @param   bool    Whether to format the file size in KB, MB, GB, TB
     * @return  mixed
     */
    public function getFileSize($file, $formatted = true) {
 
        // Set the path of the file
        $this->path = $file;
         
        // Check for a valid file path
        $this->__checkFilePath();
         
        // Get the file size in bytes
        $this->byteSize = (float) $this->__getByteSize();
         
        // If failed to get the file size or the file size is zero, return a blank result
        if (!$this->byteSize) {
            if (!$formatted) {
                return 0;
            }
             
            // Return a blank array
            $blank_size = $this->__formatFileSize();
            return array(0, $blank_size[0], $blank_size[1]);
        }
         
        // Return the bytesize if no formatting is needed
        if (!$formatted) {
            return $this->byteSize;
        }
         
        // Return an array containing the file size information
        return $this->__formatFileSize();
    }
 
    /**
     * Formats the file size in KB, MB, GB, TB units
     *
     * @access  private
     * @param   void
     * @return  array   Return arry containing the file size information
     */
    private function __formatFileSize() {
 
        // If the file size is zero return a blank result
        $_size = $this->byteSize;
        if (!$_size || $_size < 0) {
            return array(0, '0 B', array(0, 'B'));
        }
         
        // If the file size is smaller than 1KB
        if ($_size <= 1024) {
            return array(0, '1 KB', array(1, 'KB'));
        }
         
        // Set an array of all file size units
        $size_units = Array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB');
        // Set the initial unit to Bytes
        $unit = $size_units[0];
         
        // Loop through all file size units
        for ($i = 1; ($i < count($size_units) && $_size >= 1024); $i++) {
            $_size = $_size / 1024;
            $unit = $size_units[$i];
        }
         
        // Set the number of digits after the decimal place in the resulted file size
        $round = 2;
         
        // If the file size is in KiloByte we do not need any decimal numbers
        if ($unit == 'KB') {
            $round = 0;
        }
         
        // Round the file size
        $formatted = round((float) $_size, $round);
         
        // Return the file size data
        return array($this->byteSize, $formatted . " " . $unit, array($formatted, $unit));
    }
 
    /**
     * Chek if the file is exist
     *
     * @access  private
     * @param   void
     * @return  void
     */
    private function __checkFilePath() {
 
        clearstatcache();
        if (!file_exists($this->path)) {
            throw new Exception("File not found at $this->path");
        }
    }
 
    /**
     * Gets the size of the specified file in bytes
     *
     * @access  private
     * @param   void
     * @return  string  The file size in bytes
     */
    private function __getByteSize() {
 
        // Try the php native filesize() function.
        $bytesize = @filesize($this->path);
        if (false !== $bytesize && $bytesize >= 0) {
            return $bytesize;
        }
         
        // If filesize() fails with larger files, try to get the size using curl module.
        $bytesize = $this->__useCurl();
        if ($bytesize) {
            return $bytesize;
        }
         
        // If curl fails to get the file size try using the php native seek function.
        $bytesize = $this->__useNativeSeek();
        if ($bytesize) {
            return $bytesize;
        }
         
        // If the native seek fails to get the file size and we are on windows try using Windows COM interface
        $bytesize = $this->__useCom();
        if ($bytesize) {
            return $bytesize;
        }
         
        // If all the above methods failed to get the file size try using external program (exec() function needed)
        $bytesize = $this->__useExec();
        if ($bytesize) {
            return $bytesize;
        }
         
        // Unable to get the file size in bytes
        throw new Exception("Unable to get the file size for the file " . $this->path . "!");
    }
 
    /**
     * Gets the file size using curl module
     *
     * @access  private
     * @param   void
     * @return  mixed   The file size as string or false when fail or cUrl module not available
     * @see     http://www.php.net/manual/en/function.filesize.php#100434
     */
    private function __useCurl() {
 
        // If the curl module is not available return false
        if (!function_exists("curl_init")) {
            return false;
        }
         
        $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);
        curl_close($ch);
         
        if ($data !== false && preg_match('/Content-Length: (\d+)/', $data, $matches)) {
            return (string) $matches[1];
        }
    }
 
    /**
     * Gets the file size by using native fseek function
     *
     * @access  private
     * @param   void
     * @return  mixed   The file size as string or false when fail
     * @see     http://www.php.net/manual/en/function.filesize.php#79023
     * @see     http://www.php.net/manual/en/function.filesize.php#102135
     */
    private function __useNativeSeek() {
 
        // This should work for large files on 64bit platforms and for small files every where
        $fp = @fopen($this->path, "rb");
         
        // If failed to open the file return false
        if (!$fp) {
            return false;
        }
         
        flock($fp, LOCK_SH);
         
        // Seeks past the end-of-file
        $res = fseek($fp, 0, SEEK_END);
        if ($res === 0) {
            // Get the current position of the file pointer
            $pos = ftell($fp);
             
            flock($fp, LOCK_UN);
            fclose($fp);
             
            // $pos will be positive int if file is <2GB
            // if is >2GB <4GB it will be negative number
            if ($pos >= 0) {
                return (string) $pos;
            }
            else {
                return sprintf("%u", $pos);
            }
        }
        else {
            flock($fp, LOCK_UN);
            fclose($fp);
            return false;
        }
    }
 
    /**
     * Gets the file size by using Windows COM interface
     *
     * @access  private
     * @param   void
     * @return  mixed   The file size as string or false when fail or COM not available
     */
    private function __useCom() {
 
        if (!$this->isWindows || !class_exists("COM")) {
            return false;
        }
         
        // 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));
        }
         
        // Get the file data
        $f = $fsobj->GetFile($this->path);
         
        // Convert to string
        return (string) $f->Size;
    }
 
    /**
     * Gets the file size by using external program (exec needed)
     *
     * @access  private
     * @param   void
     * @return  mixed   The file size as string or false when fail or or exec is disabled
     */
    private function __useExec() {
 
        // If exeec is disable return false
        if (!function_exists("exec")) {
            return false;
        }
         
        //Escape the file path string to be used as a shell argument
        $escapedPath = escapeshellarg($this->path);
         
        // If we are on Windows
        if ($this->isWindows) {
            // Try using the NT substition modifier %~z
            $size = trim(exec("for %F in ($escapedPath) do @echo %~zF"));
        }
         
        // If other OS (*nix and MacOS)
        else {
            // If the platform is not Windows, use the stat command (should work for *nix and MacOS)
            $size = trim(exec("stat -c%s $escapedPath"));
        }
         
        // If the return is not blank, not zero, and is number
        if ($size && ctype_digit($size)) {
            return (string) $size;
        }
         
        // An error has occured
        return false;
    }
}

demo代码如下:

<?php

require ("filesizeHelper.php");
 
$filesizeHelper = new FilesizeHelper();
 
$file = 'F:\codepearl.text';
//$file = "/media/disk-1/Just.A.Very.Large.File.avi";
 
$filesize = $filesizeHelper->getFileSize($file);
 
echo "<pre>";
 
var_dump($filesize);

运行效果图:



发布了37 篇原创文章 · 获赞 4 · 访问量 58万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览