class Ftp {
private $testServer = [
'host' => 'ip',
'port' => 21,
'user' => 'userName',
'pwd' => 'password'
];
// 打開並登錄服務器
public function openServer($flag = 'test') {
$config = $this->getServerConfig($flag);
$conn = ftp_connect($config['host'], $config['port']);
if (!$conn) return 0; // 連接失敗
if (!ftp_login($conn, $config['user'], $config['pwd'])) return 1; // 登錄失敗
ftp_pasv($conn, true); // 被動模式
return $conn;
}
// 遞歸創建目錄並定位
public function makeDir($conn, $dirPath) {
$dirPath = '/' . trim($dirPath, '/');
$dirs = explode('/', $dirPath);
foreach ($dirs as $dir) {
if ($dir === '') $dir = '/';
if (@ftp_chdir($conn, $dir) === false) {
if (@ftp_mkdir($conn, $dir) === false) return 2; // 創建失敗
@ftp_chdir($conn, $dir);
}
}
return true;
}
// 上傳文件
public function upload($flag = 'test', $local, $remote) {
$conn = $this->openServer($flag);
if (is_int($conn)) return $conn; // 0或1
if ($this->makeDir($conn, dirname($remote)) === 2) return 2;
$result = ftp_put($conn, basename($remote), $local, FTP_BINARY);
$this->closeServer($conn);
return $result ? 4 : 3; // 4成功 3失敗
}
// 刪除文件
public function delete($flag = 'test', $remote) {
$conn = $this->openServer($flag);
if (is_int($conn)) return $conn;
$result = ftp_delete($conn, $remote);
$this->closeServer($conn);
return $result ? 3 : 2;
}
// 讀取目錄列表
public function read($flag, $remote) {
$conn = $this->openServer($flag);
if (is_int($conn)) return $conn;
$list = ftp_nlist($conn, $remote);
$this->closeServer($conn);
return array_values(array_filter($list, fn($v) => !in_array($v, ['.', '..'])));
}
private function getServerConfig($flag) {
return $this->testServer; // 可擴展多服務器
}
private function closeServer($conn) {
if ($conn) ftp_close($conn);
}
}
| 碼值 | 含義 | 處理建議 |
|---|---|---|
| 0 | 服務器連接失敗 | 檢查 IP/端口/防火牆 |
| 1 | 服務器登錄失敗 | 驗證用戶名密碼 |
| 2 | 創建目錄失敗 | 檢查父目錄權限 |
| 3 | 操作失敗(上傳/刪除) | 檢查磁盤空間/權限 |
| 4 | 操作成功 | 正常流程 |
$ftp = new Ftp();
// 1. 主服務器生成靜態文件後推送到從服務器
$localFile = '/var/www/html/cache/page_' . $id . '.html';
$remoteFile = '/home/www/cache/page_' . $id . '.html';
$ret = $ftp->upload('slave1', $localFile, $remoteFile);
if ($ret !== 4) {
// 記錄失敗,加入重試隊列
log_sync_failure($id, $ret);
}
// 2. 內容刪除時同步清理
$ftp->delete('slave1', $remoteFile);
// 3. 定時校驗從服務器文件完整性
$remoteFiles = $ftp->read('slave1', '/home/www/cache/');
$localFiles = glob('/var/www/html/cache/*.html');
// 對比邏輯...
getServerConfig 支持陣列配置,並發推送該類以 100 行左右代碼 解決主從文件同步核心需求,錯誤碼設計清晰,目錄遞歸創建健壯,是中小項目快速落地 FTP 同步的理想選擇。大規模場景建議對接 rsync/lsyncd 或對象存儲 CDN 方案。