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

问题描述 投票:2回答:1

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

我有一个数据库设置来记录每个客户端的存储使用情况。

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

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

我现在正在玩主要帐户中来自Cron Job的每个帐户的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); 

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


第二个脚本确实有效,但只有在手动打开时才能工作,如果由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脚本都没有安全性。

php ftp filesize
1个回答
1
投票

如果您的服务器支持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); 
        $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; 
} 

关于cron:我猜测cron没有使用正确的工作目录启动脚本,因此您需要计算不存在的目录的大小。

在这里使用绝对路径:

$directory = '../public_html/'; 

虽然你最好添加一些错误检查,以便你可以看到自己出了什么问题。

© www.soinside.com 2019 - 2024. All rights reserved.