代码之家  ›  专栏  ›  技术社区  ›  Snappysites

如何使用PHP计算FTP访问的整个目录大小

  •  2
  • Snappysites  · 技术社区  · 7 年前

    我为客户端设置了许多不同的托管帐户,需要计算每个帐户上使用的存储空间量,这些存储空间将定期更新。

    我建立了一个数据库来记录每个客户端的存储使用情况。

    我首先尝试在每个帐户上使用一个由Cron作业运行的PHP文件。如果自己手动运行,它将输出正确的文件大小,并将正确的大小更新到数据库,尽管从Cron作业运行时,它将输出0。

    然后,我尝试从主帐户的Cron作业运行此文件,但我认为这实际上不起作用,因为我的主机会阻止来自另一台服务器的文件,我最终会得到与以前相同的结果。

    我现在正在玩从主帐户的Cron作业到每个帐户的FTP访问,如下所示,唯一的问题是我不知道如何使用FTP访问计算目录大小而不是单个文件大小,也不知道如何重复这种方式?希望有人能帮上忙,免得我在这兜圈子?

    我还将添加之前的第一次尝试。

    $ftp_conn = ftp_connect($ftp_host, 21, 420) or die("Could not connect to server");
    $ftp_login = ftp_login($ftp_conn, $ftp_username, 'mypassword');
    
    $total_size = 0;                    
    $contents = ftp_nlist($ftp_conn, ".");
    // output $contents
    foreach($contents as $folder){
    
        while($search == true){
    
            if($folder == '..' || $folder == '.'){
    
            } else {
                $file = $folder; 
                $res = ftp_size($ftp_conn, $file);
    
                if ($res != -1) {
                    $total_size = $total_size + $res;
                } else {
                    $total_size = $total_size;
                }
            }
        }
    }
    
    ftp_close($ftp_conn); 
    

    这不起作用,因为它不计算文件夹大小,而且我不知道如何使用此方法打开Repeat?


    第二个脚本确实可以工作,但只有在手动打开时才能工作,如果由cron作业运行,则返回0。

    class Directory_Calculator {
    
        function calculate_whole_directory($directory)
        {
            if ($handle = opendir($directory))
            {
                $size = 0;
                $folders = 0;
                $files = 0;
    
                while (false !== ($file = readdir($handle)))
                {
                    if ($file != "." && $file != "..")
                    {
                        if(is_dir($directory.$file))
                        {
                        $array = $this->calculate_whole_directory($directory.$file.'/');
                        $size += $array['size'];
                        $files += $array['files'];
                        $folders += $array['folders'];
                        }
                        else
                        {
                        $size += filesize($directory.$file);
                        $files++;
                        }
                    }
                }
                closedir($handle);
            }
    
            $folders++;
    
            return array('size' => $size, 'files' => $files, 'folders' => $folders);
        }
    
    }
    
    /* Path to Directory - IMPORTANT: with '/' at the end */
    $directory = '../public_html/'; 
    
    // return an array with: size, total files & folders
    $array = $directory_size->size($directory); 
    
    $size_of_site = $array['size'];
    
    echo $size_of_site;
    

    请记住,我目前正在测试,MySQLi或PHP脚本都还不安全。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Martin Prikryl    5 年前

    如果您的服务器支持 MLSD 命令,并且您有PHP 7.2或更新版本,您可以使用 ftp_mlsd function :

    function calculate_whole_directory($ftp_conn, $directory)
    {
        $files = ftp_mlsd($ftp_conn, $directory) or die("Cannot list $directory");
        $result = 0;
        foreach ($files as $file)
        { 
            if (($file["type"] == "cdir") || ($file["type"] == "pdir"))
            {
                $size = 0;
            }
            else if ($file["type"] == "dir")
            {
                $size = calculate_whole_directory($ftp_conn, $directory."/".$file["name"]);
            }
            else
            {
                $size = intval($file["size"]);
            }
            $result += $size;
        } 
    
        return $result; 
    } 
    

    如果没有PHP 7.2,可以尝试实现 MLSD 自己指挥。首先,请参阅的用户注释 ftp_rawlist 命令:
    https://www.php.net/manual/en/function.ftp-rawlist.php#101071


    如果无法使用 MLSD ,您在判断 entry is a file or folder . 而您可以使用 ftp_size 技巧,就像你做的那样,打电话 ftp_size 因为每个条目都可能需要很长时间。

    但是,如果只需要针对一个特定的FTP服务器,可以使用 ftp_rawlist 以特定于平台的格式检索文件列表并对其进行分析。

    以下代码采用通用的*nix格式。

    function calculate_whole_directory($ftp_conn, $directory)
    {
        $lines = ftp_rawlist($ftp_conn, $directory) or die("Cannot list $directory");
        $result = 0;
        foreach ($lines as $line)
        { 
            $tokens = preg_split("/\s+/", $line, 9); 
            $name = $tokens[8];
            if ($tokens[0][0] === 'd')
            {
                $size = calculate_whole_directory($ftp_conn, "$directory/$name");
            }
            else
            {
                $size = intval($tokens[4]);
            }
            $result += $size;
        } 
    
        return $result; 
    } 
    

    基于 PHP FTP recursive directory listing .


    关于cron:我猜cron并没有用正确的工作目录启动脚本,所以需要计算一个不存在的目录的大小。

    在此处使用绝对路径:

    $directory = '../public_html/'; 
    

    尽管您最好添加一些错误检查,这样您就可以看到自己出了什么问题。