You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:17:36