PHP FTP远程服务器备份脚本开发求助:递归遍历目录问题
问题分析
你代码卡住的核心原因是**RecursiveDirectoryIterator只能遍历本地文件系统**,它无法直接读取远程FTP服务器的目录结构。要实现远程FTP的递归遍历,得用PHP FTP扩展提供的函数手动实现递归逻辑。
解决方案
下面是完整的实现脚本,包含远程目录递归遍历、本地目录创建、增量备份(仅复制新文件/更新文件)的功能:
<?php $ftp_server = "ftp.servername.com"; $ftp_username = "username"; $ftp_password = "password"; $local_dir = "/Local-Copy"; $remote_dir = "Starting-Directory/"; // 建立FTP连接 $conn_id = ftp_connect($ftp_server) or die("无法连接到 $ftp_server"); $login_result = ftp_login($conn_id, $ftp_username, $ftp_password); if ((!$conn_id) || (!$login_result)) { echo "FTP连接失败:服务器 $ftp_server,用户 $ftp_username <br>"; exit; } else { echo "已连接到服务器 $ftp_server,用户 $ftp_username <br>"; } ftp_pasv($conn_id, true); // 启用被动模式 // 递归遍历远程FTP目录并同步到本地 function sync_ftp_directory($conn_id, $remote_path, $local_path) { // 创建本地目录(如果不存在) if (!is_dir($local_path)) { mkdir($local_path, 0755, true); echo "创建本地目录:$local_path <br>"; } // 获取远程目录下的所有条目(文件+子目录) $remote_entries = ftp_nlist($conn_id, $remote_path); if (!$remote_entries) { echo "无法读取远程目录:$remote_path <br>"; return; } foreach ($remote_entries as $entry) { // 跳过.和..目录 if (basename($entry) === "." || basename($entry) === "..") { continue; } $remote_entry_path = $entry; $local_entry_path = $local_path . DIRECTORY_SEPARATOR . basename($entry); // 判断当前条目是文件还是目录 // 通过尝试获取文件大小来判断:如果是目录,ftp_size会返回-1 $file_size = ftp_size($conn_id, $remote_entry_path); if ($file_size === -1) { // 是目录,递归处理 sync_ftp_directory($conn_id, $remote_entry_path, $local_entry_path); } else { // 是文件,检查是否需要下载 $need_download = false; // 如果本地文件不存在,直接下载 if (!file_exists($local_entry_path)) { $need_download = true; } else { // 对比远程和本地文件的修改时间,只下载更新过的文件 $remote_mtime = ftp_mdtm($conn_id, $remote_entry_path); $local_mtime = filemtime($local_entry_path); if ($remote_mtime > $local_mtime) { $need_download = true; } } if ($need_download) { // 下载文件 if (ftp_get($conn_id, $local_entry_path, $remote_entry_path, FTP_BINARY)) { echo "已下载:$remote_entry_path -> $local_entry_path <br>"; // 同步文件修改时间 touch($local_entry_path, $remote_mtime); } else { echo "下载失败:$remote_entry_path <br>"; } } else { echo "跳过已同步文件:$remote_entry_path <br>"; } } } } // 开始同步 sync_ftp_directory($conn_id, $remote_dir, $local_dir); // 关闭FTP连接 ftp_close($conn_id); echo "FTP连接已关闭,同步完成 <br>"; ?>
关键说明
- 递归目录遍历:通过自定义
sync_ftp_directory函数,用ftp_nlist获取远程目录条目,递归处理子目录 - 文件判断:用
ftp_size判断远程条目是文件还是目录(目录的ftp_size返回-1) - 增量备份:对比远程文件的修改时间(
ftp_mdtm)和本地文件的修改时间,仅下载新文件或更新过的文件 - 本地目录创建:用
mkdir(..., true)递归创建多级目录 - 文件同步优化:下载后用
touch同步本地文件的修改时间,避免下次重复判断
内容的提问来源于stack exchange,提问作者ChettaiChangz
相关产品推荐
相关产品推荐

