PHP FTP recursive directory listing
P粉621033928
2023-08-25 00:36:20
<p>I'm trying to create a recursive function to get all directories and subdirectories from an ftp server in an array. </p>
<p>I tried a lot of features I found online. The one that works best for me is this: </p>
<pre class="brush:php;toolbar:false;">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;
}</pre>
<p>The problem with this function is that it does not allow directories to have "."Every file located in the root directory will also be considered a directory in its name. So I tweaked the function and got this: </p>
<pre class="brush:php;toolbar:false;">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;
}</pre>
<p>This works fine but gives the results I want. But it's too slow to use. </p>
<p>I also tried using <code>ftp_rawlist</code> but it had the same drawback of being very slow. </p>
<pre class="brush:php;toolbar:false;">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;
}</pre>
<p>I have been troubled by this problem for the past few days, and I am getting more and more desperate. If anyone has any suggestions please let me know</p>
I built an OOP FTP client library that can help you solve this problem a lot, using just this code you can retrieve a directory listing with just additional useful information like (chmod, last modification time, size...).
Code:
If your server supports the
MLSD
command and you have PHP 7.2 or higher, you can use theftp_mlsd
function :If you don't have PHP 7.2, you can try to implement the
MLSD
command yourself. First, see the user notes for theftp_rawlist
command:https://www.php.net/manual/en/ function.ftp-rawlist.php#101071
If you are unable to use
However, if you only need to work against one specific FTP server, you can useMLSD
, you will particularly have problems determining whether an entry is a file or a folder . While you can use theftp_size
trick, calling ftp_sizefor each entry can take a long time.
ftp_rawlist
The following code assumes common *nix format.to retrieve a list of files in a platform-specific format and parse it.
Get directory structure from FTP using PHP.