PHP FTP递归目录列表

时间:2016-03-30 13:26:07

标签: php recursion ftp

我试图制作一个递归函数,从数组中的ftp服务器获取所有目录和子目录。

我尝试了很多我在网上找到的功能。对我来说效果最好的是这一个:

public function getAllSubDirFiles() {
    $dir = array(".");
    $a = count($dir);
    $i = 0;
    $depth = 20;
    $b = 0;
    while (($a != $b) && ($i < $depth)) {
        $i++;
        $a = count($dir);
        foreach ($dir as $d) {
            $ftp_dir = $d . "/";
            $newdir = ftp_nlist($this->connectionId, $ftp_dir);
            foreach ($newdir as $key => $x) {

                if ((strpos($x, ".")) || (strpos($x, ".") === 0)) {
                    unset($newdir[$key]);
                } elseif (!in_array($x, $dir)) {
                    $dir[] = $x;
                }
            }
        }
        $b = count($dir);
    }
    return $dir ;

}

这个功能的问题是它不允许目录有一个&#34;。&#34;在它的名称中,位于根目录中的每个文件也将被视为目录。所以我调整了功能,得到了这个:

public function getAllSubDirFiles($ip, $id, $pw) {
    $dir = array(".");
    $a = count($dir);
    $i = 0;
    $depth = 20;
    $b =0;
    while (($a != $b) && ($i < $depth)) {
        $i++;
        $a = count($dir);
        foreach ($dir as $d) {
            $ftp_dir = $d . "/";
            $newdir = ftp_nlist($this->connectionId, $ftp_dir);
            foreach ($newdir as $key => $x) {
                if (!is_dir('ftp://'.$id.':'.$pw.'@'.$ip.'/'.$x)) {
                    unset($newdir[$key]);
                } elseif (!in_array($x, $dir)) {
                    $dir[] = $x;
                }
            }
        }
        $b = count($dir);
    }
    return $dir ;

}

这非常好用但是给出了我想要的结果。但它的速度太慢,无法使用。

我也尝试过与ftp_rawlist合作,但它有同样的缺点,即速度非常慢。

public function getAllSubDirFiles() {
    $dir = array(".");
    $a = count($dir);
    $i = 0;
    $depth = 20;
    $b = 0;
    while (($a != $b) && ($i < $depth)) {
        $i++;
        $a = count($dir);
        foreach ($dir as $d) {
            $ftp_dir = $d . "/";
            $newdir = $this->getFtp_rawlist('/' . $ftp_dir);
            foreach ($newdir as $key => $x) {

                $firstChar = substr($newdir[$key][0], 0, 1);

                $a = 8;
                    while ($a < count($newdir[$key])) {

                        if ($a == 8) {
                            $fileName = $ftp_dir . '/' . $newdir[$key][$a];
                        } else {
                            $fileName = $fileName . ' ' . $newdir[$key][$a];
                        }
                        $a++;
                    }

                if ($firstChar != 'd') {
                    unset($newdir[$key]);
                } elseif (!in_array($fileName, $dir)) {

                    $dir[] = $fileName;
                }
            }
        }
        $b = count($dir);
    }
    return $dir;
}

public function getFtp_rawlist($dir) {

    $newArr = array();

    $arr = ftp_rawlist($this->connectionId, $dir);

    foreach ($arr as $value) {

        $stringArr = explode(" ", $value);

        $newArr[] = array_values(array_filter($stringArr));
    }
    return $newArr;
}

在过去的几天里我一直坚持这个问题而且我已经绝望了。如果有人有任何建议请告诉我

3 个答案:

答案 0 :(得分:1)

您必须使用目录列表命令来检索有关文件系统条目的详细信息,以便您可以检测条目是文件还是文件夹。

使用ftp_rawlist。这具有列表具有未定义语法的缺点。但是,如果您只连接到一台服务器(或仅一台服务器类型),如果不是大问题。

我看到你已经使用ftp_rawlist了。但是你的代码是错的。它一遍又一遍地重读同一个文件夹。

使用简单的递归,如:

function ftp_list_files_recursive($ftp_stream, $path)
{
    $lines = ftp_rawlist($ftp_stream, $path);

    $result = array();

    foreach ($lines as $line)
    {
        $tokens = explode(" ", $line);
        $name = $tokens[count($tokens) - 1];
        $type = $tokens[0][0];
        $filepath = $path . "/" . $name;

        if ($type == 'd')
        {
            $result =
                array_merge($result, ftp_list_files_recursive($ftp_stream, $filepath));
        }
        else
        {
            $result[] = $filepath;
        }
    }
    return $result;
}

答案 1 :(得分:1)

我已经构建了一个OOP FTP Client library,可以为您提供很多帮助,仅使用此代码,您就可以检索仅包含目录的列表以及其他有用信息,例如(chmod,上次修改时间,大小)。 ..)。

代码:

// Connection
$connection = new FtpConnection("localhost", "foo", "12345");
$connection->open();
        
// FtpConfig
$config = new FtpConfig($connection);
$config->setPassive(true);

$client = new FtpClient($connection);

$allFolders =
    // directory, recursive, filter
    $client->listDirectoryDetails('/', true, FtpClient::DIR_TYPE); 

// Do whatever you want with the folders

答案 2 :(得分:0)

此代码是Martin Prikryl的变体之一。它比较慢,但没有任何空白失败。仅当您对上述代码有任何问题时才使用此代码。

function ftp_list_files_recursive($ftp_stream, $path){
    $lines = ftp_nlist($ftp_stream, $path);
    $result = array();
    foreach ($lines as $line) {
        if (ftp_size($ftp_stream, $line) == -1) {
            $result = array_merge($result, ftp_list_files_recursive($ftp_stream, $line));
        }
        else{
            $result[] = $line;
        }
    }
    return $result;
}