I'm trying to get a list of files from an FTP directory but the ftp_nlist function repeatedly returns false. I've tried this on 3 different FTP servers with the same result. In each case, I was able to connect and download files using ftp_fget, but ftp_nlist never works. Any ideas why? Here is the code:
<?php
$ftp_server = "myhost";
$ftp_user_name = "myuser";
$ftp_user_pass = "mypass";
$remote_dir = "test/"; // The directory on the FTP server
$local_dir = "test/"; // Local directory to save the files
// Connect to the FTP server
$conn_id = ftp_connect($ftp_server);
if (!$conn_id) {
die("Could not connect to FTP server $ftp_server");
}
// Log in to the server
if (!ftp_login($conn_id, $ftp_user_name, $ftp_user_pass)) {
die("Could not log in to FTP server with provided credentials.");
}
// Enable passive mode
ftp_pasv($conn_id, true);
if (!ftp_chdir($conn_id, $remote_dir)) {
ftp_close($conn_id);
die("Could not change to directory: $remote_dir");
}
// Check if the local directory exists, if not create it
if (!is_dir($local_dir)) {
if (!mkdir($local_dir, 0777, true)) {
die("Failed to create local directory: $local_dir");
}
}
// Download a file - THIS WORKS!
$remote_file='test.txt';
$local_file='test.txt';
$handle = fopen($local_file, 'w');
if (ftp_fget($conn_id, $handle, $remote_file, FTP_ASCII, 0)) {
echo "successfully written to $local_file\n";
} else {
echo "There was a problem while downloading $remote_file to $local_file\n";
}
// Get the list of files in the remote directory
$files = ftp_nlist($conn_id, $remote_dir);
//$files = ftp_nlist($conn_id, '');
if ($files === false) {
die("Could not list files in the remote directory: $remote_dir");
}
foreach ($files as $file) {
// Get the base name of the file
$basename = basename($file);
// Build the local file path
$local_file = $local_dir . $basename;
// Attempt to download the file
if (ftp_get($conn_id, $local_file, $file, FTP_BINARY)) {
echo "Successfully downloaded $file to $local_file\n";
} else {
echo "Failed to download $file\n";
}
}
// Close the FTP connection
ftp_close($conn_id);
echo "FTP download completed.\n";
?>
A very small reproduceable example of your problem is below
$remote_dir = "test/";
ftp_chdir($conn_id, $remote_dir);
var_dump(ftp_nlist($conn_id, $remote_dir));
The second line changes the FTP connection's remote directory to test/
. Note that there is no leading /
so it is relative to whatever the current CWD is. You are then asking for a directory listing using the same variable which means it is relative to the last call that changed CWD, effectively test/test/
.
There's a couple of possible fixes that I can think of.
The easiest probably is as @Olivier pointed out in the comments and just use .
as the second argument to ftp_nlist
which would mean "give me the list of files in the current directory":
var_dump(ftp_nlist($conn_id, '.'));
The second option is to just not issue the ftp_chdir
command in the first place. This mostly depends on what else you are doing, and whether you care about the CWD at all, which I think your code does. So possibly this is not for you.
The last option is to just use absolute directories, so instead of test/
use /test/
. This would allow you to use ftp_chdir
both ftp_nlist
with the same variable and talk about the same directory. The choice to do this, once again, depends on the intentions of your code.