Laravel 8+Flysystem FTP连接失败求助(FileZilla可正常连接)
解决Laravel+Flysystem/纯PHP FTP连接失败但FileZilla正常的问题
核心问题分析
你遇到的是典型的PHP FTP扩展与FileZilla在被动模式地址解析上的差异:当FTP服务器处于NAT(端口映射)环境时,FileZilla会自动识别并忽略服务器返回的内部被动地址,改用连接时的公网IP;但PHP默认会严格使用服务器返回的被动地址,导致连接失败。另外你的代码里还有几处细节错误需要修正。
解决方案1:修正Flysystem FTP配置
你的配置里重复定义了passive参数,且缺少关键的ignorePassiveAddress设置,调整如下:
use League\Flysystem\Filesystem; use League\Flysystem\Adapter\Ftp; $adapter = new Ftp([ 'host' => $ftp_server, 'username' => $ftp_username, 'password' => $ftp_password, 'port' => 2526, 'passive' => true, // 和FileZilla保持一致,只保留一次设置 'ssl' => false, 'tls' => false, 'timeout' => 400, 'utf8' => false, 'transferMode' => FTP_BINARY, 'systemType' => null, 'ignorePassiveAddress' => true, // 关键:忽略服务器返回的内部被动地址,使用连接IP 'timestampsOnUnixListingsEnabled' => false, 'recurseManually' => true ]); $filesystem = new Filesystem($adapter); // 建议先尝试列出目录而非检查单个文件,避免路径不存在导致误判 try { $contents = $filesystem->listContents('/'); echo "FTP连接成功!"; } catch (\Exception $e) { echo "连接失败:" . $e->getMessage(); }
解决方案2:修正纯PHP FTP代码错误
你的代码里存在变量名错误,同时需要手动开启被动地址忽略:
// File details $fileName = 'example.txt'; $fileContents = 'This is the content of the file.'; // Create a temporary file $tempFile = tmpfile(); fwrite($tempFile, $fileContents); fseek($tempFile, 0); // Connect to FTP server $connId = ftp_connect($ftpServer, $ftpPort); if ($connId) { // Login to FTP server $loginResult = ftp_login($connId, $ftpUsername, $ftpPassword); if ($loginResult) { // 启用被动模式,并设置忽略被动地址(PHP>=7.3支持) ftp_pasv($connId, true); ini_set('ftp.ignore_passive_address', true); // 建议用二进制模式传输,避免编码问题 $upload = ftp_fput($connId, $fileName, $tempFile, FTP_BINARY); if (!$upload) { die('文件上传失败:' . error_get_last()['message']); } // Close the temporary file fclose($tempFile); // 修正变量名错误 ftp_close($connId); echo '文件创建成功。'; } else { echo 'FTP登录失败。'; } } else { echo '无法连接到FTP服务器。'; }
额外排查点
- 检查被动端口范围:如果FTP服务器配置了被动端口范围(如21000-22000),确保服务器防火墙/安全组开放了这些端口,且PHP所在服务器能访问它们。
- 尝试加密连接:即使你设置了
ssl=false,可以尝试开启tls=true,部分服务器强制要求加密连接但FileZilla会自动适配。 - 验证路径正确性:确认
$path是FTP服务器上真实存在的路径,避免因文件不存在导致has()方法返回false,误判为连接失败。
内容的提问来源于stack exchange,提问作者Tigane
相关产品推荐
相关产品推荐

