我的应用程序连接到通过VPN连接到服务器的FTP客户端。到目前为止,所有客户端都支持活动PHP,我使用的库默认使用活动FTP,所以没有问题。现在我们已经安装了一些不能正常运行PHP的新客户端,所以我发现从服务器(通过FTP cli和FileZilla over RDP)可以通过被动连接连接到所有客户端并与之通信
但是,当尝试在PHP中建立被动连接时,所有FTP命令(例如nlist
)都会超时。我遇到了this blog post,它提供了针对特定被动FTP问题的补丁(现在可以在常规PHP版本中使用),所以我尝试了这样测试:
$conn = ftp_connect($address);
$login = ftp_login($conn, 'username', 'password');
ftp_set_option($conn, USEPASVADDRESS, false);
ftp_pasv($conn, true);
$contents = ftp_nlist($conn, '.');
var_dump($contents);
ftp_close($conn);
ftp_pasv
返回true,因此它会切换到被动模式,但ftp_nlist
超时,这对于活动模式和兼容客户端来说都不是。
PHP的FTP实现与FTP cli应用程序有什么不同?
答案 0 :(得分:-1)
我想我已经弄清楚在我的情况下确切的问题是什么。我不确定这对其他人是否有帮助,但如果您遇到类似问题,不妨研究一下。
当激活被动模式时,服务器会告诉您一个 IP 和一个端口,用于连接数据传输。使用 ftp
CLI 时,实际的 PASV
命令仅在您发送数据命令(例如请求文件夹内容)时发送。在这些情况下,CLI 发送 PASV
命令,接收 IP/端口,连接到它,然后通过它发送原始命令 (LIST
)。
PHP 似乎以不同的方式执行此操作:一旦您在我们的代码中切换到被动连接,它就会发送 PASV
命令并立即从服务器接收 IP/端口 - 但 PHP 尚未连接到它。当我请求目录列表时,首先激活 ASCII 模式,然后才连接到先前接收到的 IP/端口以发送 LIST
命令。
因此,我怀疑我连接的 FTP 服务器有问题。我的想法是,一旦它收到 PASV
命令,它会等待直到有人真正连接到该被动连接,然后才开始接受任何其他命令。事实上,我设法验证了这一点。当 PHP 脚本仍在等待响应时,我手动建立了到接收到的被动端口的 TCP 连接,之后我的 PHP 代码继续运行并显示结果。
对我来说不幸的是,这意味着我根本无法在这些服务器上使用被动 FTP,并且无法更新/切换到不同的服务器实现。主动 FTP 也几乎不可能,因为我的应用程序在 Docker 中运行。