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

如何使用PHP计算FTP访问的整个目录大小,php,ftp,filesize,Php,Ftp,Filesize,我为客户设置了许多不同的托管帐户,需要计算每个帐户上使用的存储空间量,并定期更新 我建立了一个数据库来记录每个客户端的存储使用情况 我首先尝试在每个帐户上使用一个PHP文件,由Cron作业运行。如果由我自己手动运行,它将输出正确的文件大小并将正确的大小更新到数据库,尽管从Cron作业运行时,它将输出0 然后,我尝试从主帐户的Cron作业运行此文件,但我认为这实际上不起作用,因为我的主机将阻止来自另一台服务器的文件,我最终会得到与以前相同的结果 我现在正在玩从主帐户的Cron作业到每个帐户的FTP

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

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

我首先尝试在每个帐户上使用一个PHP文件,由Cron作业运行。如果由我自己手动运行,它将输出正确的文件大小并将正确的大小更新到数据库,尽管从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); 
这不起作用,因为它不计算文件夹大小,我不知道如何使用此方法打开文件夹


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

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

如果您没有PHP7.2,您可以尝试自己实现
MLSD
命令。首先,请参阅
ftp\u rawlist
命令的用户注释:


如果您不能使用
MLSD
,您将特别难以判断是否存在错误。虽然您可以使用
ftp\u size
技巧,但调用每个条目可能需要很长时间

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

以下代码采用通用*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; 
} 

基于


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

在此处使用绝对路径:

$directory = '../public_html/'; 

不过,您最好添加一些错误检查,这样您就可以看到出现了什么问题。

您是否仔细检查了cmd行php和apache php的配置是否相同?(cron作业使用cmd行php)是的,cron作业确实可以工作,我可以看到结果,但是由于某种原因,它以这种方式运行时返回0-当它手动运行时,它似乎可以工作?啊,那么您也可以通过cmd行手动运行它吗?这对克朗来说很奇怪。这可能是因为cron是以root用户身份运行的,而cmd行的手动运行是由用户执行的?除非你也是苏茵,否则情况就不是这样了。呵呵。。。只是在我脑子里转来转去。每当我遇到手动运行与从cron作业运行的差异时,通常是apache与cmd,或者root与apache用户,等等。这可能不是您的问题:(不,对不起,当我手动运行它时,我的意思是我使用浏览器导航到PHP文件,而不是从cmd行。对不起,我没有更清楚。当您执行手动运行的第二个脚本时,但是使用cron执行0…您的所有帐户目录实际上都是“本地的”(
$directory='../public_html/';
)?如果是这样的话,那么是的,不需要使用FTP路由,因为所有目录都与脚本位于同一服务器上。这样就减少了需要考虑的代码…或者我被这个问题弄糊涂了LOL!我是一个空白。感谢描述性的回答,这个方法可能是解决我问题的最佳方法。似乎我可能会被手动pr卡住正在处理脚本,但至少计算正确!谢谢。
$directory = '../public_html/';