PHP ftp_pasv() 函数用于开启或关闭FTP连接的被动模式(PASV模式)。
ftp_pasv(resource $ftp, bool $pasv): bool
| 参数 | 描述 |
|---|---|
ftp |
必需。FTP连接的标识符,由ftp_connect()或ftp_ssl_connect()返回 |
pasv |
必需。如果为 true,则开启被动模式;如果为 false,则关闭被动模式(即主动模式) |
truefalseftp_pasv($ftp, false)ftp_pasv())ftp_pasv($ftp, true)FTP主动模式与被动模式连接示意图
<?php
// 连接FTP服务器
$ftp_server = "ftp.example.com";
$ftp_user = "username";
$ftp_pass = "password";
$ftp_conn = ftp_connect($ftp_server);
if (!$ftp_conn) {
die("无法连接到 $ftp_server");
}
// 登录
if (!ftp_login($ftp_conn, $ftp_user, $ftp_pass)) {
die("登录失败");
}
echo "当前模式: " . (ftp_pasv($ftp_conn, false) ? "主动模式" : "未知") . "\n";
// 开启被动模式
if (ftp_pasv($ftp_conn, true)) {
echo "成功开启被动模式\n";
// 现在可以进行文件传输操作
$file_list = ftp_nlist($ftp_conn, "/");
if ($file_list !== false) {
echo "目录列表:\n";
foreach ($file_list as $file) {
echo " - $file\n";
}
}
// 下载文件示例
$remote_file = "example.txt";
$local_file = "download.txt";
if (ftp_get($ftp_conn, $local_file, $remote_file, FTP_BINARY)) {
echo "文件下载成功: $local_file\n";
} else {
echo "文件下载失败\n";
}
} else {
echo "开启被动模式失败\n";
// 尝试使用主动模式
echo "尝试使用主动模式...\n";
ftp_pasv($ftp_conn, false);
// 继续操作
$file_list = ftp_nlist($ftp_conn, "/");
// ...
}
// 关闭FTP连接
ftp_close($ftp_conn);
?>
<?php
class SmartFTPClient {
private $ftp_conn;
private $mode = 'unknown'; // 'active' 或 'passive'
public function connect($server, $username, $password) {
$this->ftp_conn = ftp_connect($server);
if (!$this->ftp_conn) {
return false;
}
if (!ftp_login($this->ftp_conn, $username, $password)) {
return false;
}
// 尝试自动检测最佳模式
$this->autoDetectMode();
return true;
}
private function autoDetectMode() {
// 首先尝试被动模式(现代网络更常用)
if ($this->testConnection(true)) {
$this->mode = 'passive';
echo "✓ 被动模式可用\n";
return;
}
// 如果被动模式失败,尝试主动模式
if ($this->testConnection(false)) {
$this->mode = 'active';
echo "✓ 主动模式可用\n";
return;
}
// 两种模式都失败
$this->mode = 'unknown';
echo "✗ 无法确定可用模式\n";
}
private function testConnection($usePassive) {
// 设置模式
if (!ftp_pasv($this->ftp_conn, $usePassive)) {
return false;
}
// 尝试一个简单的操作来测试连接
try {
// 尝试获取当前目录(简单且快速的操作)
$pwd = @ftp_pwd($this->ftp_conn);
if ($pwd !== false) {
return true;
}
} catch (Exception $e) {
// 忽略错误
}
return false;
}
public function setMode($mode) {
if ($mode === 'passive') {
if (ftp_pasv($this->ftp_conn, true)) {
$this->mode = 'passive';
return true;
}
} elseif ($mode === 'active') {
if (ftp_pasv($this->ftp_conn, false)) {
$this->mode = 'active';
return true;
}
}
return false;
}
public function getMode() {
return $this->mode;
}
public function getCurrentModeStatus() {
// 获取当前实际模式状态
// 注意:PHP没有直接获取当前模式状态的函数,这里通过测试推断
$original_mode = $this->mode;
// 测试被动模式
if ($this->testConnection(true)) {
// 恢复原模式
$this->setMode($original_mode);
return 'passive';
}
// 测试主动模式
if ($this->testConnection(false)) {
// 恢复原模式
$this->setMode($original_mode);
return 'active';
}
return 'unknown';
}
public function listDirectory($directory = '') {
// 确保使用当前设置的模式
$this->setMode($this->mode);
$items = ftp_nlist($this->ftp_conn, $directory);
if ($items === false) {
// 如果失败,尝试另一种模式
$alternative_mode = ($this->mode === 'passive') ? 'active' : 'passive';
$this->setMode($alternative_mode);
$items = ftp_nlist($this->ftp_conn, $directory);
if ($items !== false) {
// 切换模式成功,更新当前模式
$this->mode = $alternative_mode;
echo "自动切换到 {$alternative_mode} 模式\n";
}
}
return $items;
}
public function downloadFile($remote_file, $local_file) {
// 设置模式
$this->setMode($this->mode);
$result = ftp_get($this->ftp_conn, $local_file, $remote_file, FTP_BINARY);
if (!$result && $this->mode === 'passive') {
// 如果被动模式失败,尝试主动模式
echo "被动模式下载失败,尝试主动模式...\n";
$this->setMode('active');
$result = ftp_get($this->ftp_conn, $local_file, $remote_file, FTP_BINARY);
if ($result) {
$this->mode = 'active';
}
}
return $result;
}
public function __destruct() {
if ($this->ftp_conn) {
ftp_close($this->ftp_conn);
}
}
}
// 使用示例
$ftp = new SmartFTPClient();
if ($ftp->connect('localhost', 'user', 'pass')) {
echo "连接成功,当前模式: " . $ftp->getMode() . "\n";
// 列出目录
$files = $ftp->listDirectory('/');
if ($files !== false) {
echo "找到 " . count($files) . " 个文件/目录:\n";
foreach ($files as $file) {
echo " - $file\n";
}
}
// 下载文件
if ($ftp->downloadFile('/example.txt', 'local_example.txt')) {
echo "文件下载成功\n";
} else {
echo "文件下载失败\n";
}
// 手动切换模式
if ($ftp->setMode('passive')) {
echo "已切换到被动模式\n";
}
} else {
echo "连接失败\n";
}
?>
<?php
function robustFTPConnect($server, $username, $password, $port = 21, $timeout = 30) {
$ftp_conn = ftp_connect($server, $port, $timeout);
if (!$ftp_conn) {
throw new Exception("无法连接到服务器: $server:$port");
}
// 设置连接超时
ftp_set_option($ftp_conn, FTP_TIMEOUT_SEC, $timeout);
if (!@ftp_login($ftp_conn, $username, $password)) {
ftp_close($ftp_conn);
throw new Exception("登录失败,用户名或密码错误");
}
return $ftp_conn;
}
function diagnoseConnectionIssues($ftp_conn) {
echo "开始诊断FTP连接问题...\n";
// 测试1:检查基本连接
echo "1. 检查基本连接... ";
$pwd = @ftp_pwd($ftp_conn);
if ($pwd !== false) {
echo "✓ 当前目录: $pwd\n";
} else {
echo "✗ 无法获取当前目录\n";
return false;
}
// 测试2:尝试被动模式
echo "2. 测试被动模式... ";
if (@ftp_pasv($ftp_conn, true)) {
$list_passive = @ftp_nlist($ftp_conn, ".");
if ($list_passive !== false) {
echo "✓ 被动模式可用 (" . count($list_passive) . " 个项目)\n";
} else {
echo "✗ 被动模式设置成功但无法列出目录\n";
}
} else {
echo "✗ 无法设置被动模式\n";
}
// 测试3:尝试主动模式
echo "3. 测试主动模式... ";
if (@ftp_pasv($ftp_conn, false)) {
$list_active = @ftp_nlist($ftp_conn, ".");
if ($list_active !== false) {
echo "✓ 主动模式可用 (" . count($list_active) . " 个项目)\n";
} else {
echo "✗ 主动模式设置成功但无法列出目录\n";
}
} else {
echo "✗ 无法设置主动模式\n";
}
// 测试4:测试数据传输
echo "4. 测试数据传输... ";
$test_file = "test_" . time() . ".txt";
$test_content = "FTP connection test at " . date('Y-m-d H:i:s');
file_put_contents($test_file, $test_content);
// 尝试上传
if (@ftp_put($ftp_conn, $test_file, $test_file, FTP_ASCII)) {
echo "✓ 文件上传成功\n";
// 尝试下载
$downloaded_file = "downloaded_" . $test_file;
if (@ftp_get($ftp_conn, $downloaded_file, $test_file, FTP_ASCII)) {
echo "✓ 文件下载成功\n";
// 清理测试文件
@ftp_delete($ftp_conn, $test_file);
@unlink($test_file);
@unlink($downloaded_file);
} else {
echo "✗ 文件下载失败\n";
}
} else {
echo "✗ 文件上传失败\n";
@unlink($test_file);
}
// 测试5:检查服务器特性
echo "5. 检查服务器特性... ";
$system_type = @ftp_systype($ftp_conn);
if ($system_type !== false) {
echo "✓ 服务器类型: $system_type\n";
} else {
echo "✗ 无法获取服务器类型\n";
}
return true;
}
// 使用示例
try {
echo "=== FTP连接诊断工具 ===\n";
// 连接参数
$server = 'localhost';
$username = 'user';
$password = 'pass';
// 建立连接
$ftp_conn = robustFTPConnect($server, $username, $password);
// 运行诊断
diagnoseConnectionIssues($ftp_conn);
// 根据诊断结果提供建议
echo "\n=== 建议 ===\n";
// 检查是否成功设置过模式
$test_passive = @ftp_pasv($ftp_conn, true);
$test_active = @ftp_pasv($ftp_conn, false);
if ($test_passive && !$test_active) {
echo "1. 建议使用被动模式 (ftp_pasv(\$ftp, true))\n";
echo "2. 检查服务器防火墙是否允许被动模式端口范围\n";
echo "3. 确保客户端防火墙允许出站连接\n";
} elseif (!$test_passive && $test_active) {
echo "1. 建议使用主动模式 (ftp_pasv(\$ftp, false))\n";
echo "2. 检查客户端防火墙是否允许入站连接到高端口\n";
echo "3. 可能需要配置客户端防火墙例外\n";
} elseif ($test_passive && $test_active) {
echo "1. 两种模式都可用,推荐使用被动模式\n";
echo "2. 被动模式更适用于现代网络环境\n";
} else {
echo "1. 两种模式都不可用,可能存在严重网络问题\n";
echo "2. 检查网络连接和防火墙设置\n";
echo "3. 联系网络管理员确认FTP服务器状态\n";
}
// 关闭连接
ftp_close($ftp_conn);
echo "\n诊断完成\n";
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
?>
ftp_get()、ftp_put())之前,应该先设置好模式ftp_ssl_connect()),模式设置同样适用ftp_pasv($ftp, true)ftp_nlist()ftp_pasv($ftp, false)并重试ftp_connect() - 建立FTP连接ftp_ssl_connect() - 建立SSL-FTP连接ftp_login() - 登录FTP服务器ftp_get() - 从FTP服务器下载文件ftp_put() - 上传文件到FTP服务器ftp_nlist() - 列出FTP目录中的文件ftp_set_option() - 设置各种FTP运行时选项