PHP 的 ftp_raw 函数与 MLSD 和 fsockopen:奇怪的阻塞行为和警告信息
PHP's ftp_raw function with MLSD and fsockopen: weird blocking behaviour and Warning messages
我目前在使用 FTP 的 ftp_raw
功能时遇到问题。
我需要获取 FTP 目录的非常精确和详细的文件和目录列表(ftp_rawlist
对日期时间不够精确,因此未指定)。所以我想使用更规范化的命令:MLSD
。
我可以获得我想要的文件列表,但是从套接字中获取数据后,无法再使用 PHP 的 ftp*
功能...
这是我的代码的摘录:
//Current folder = "/"
$directory = "/www/";
$currentFolder = ftp_pwd($ftpStream);
echo $currentFolder;
echo ' : ';
ftp_chdir($ftpStream, $directory);
$ret = ftp_raw($ftpStream, 'PASV');
if (preg_match('#^227.*\(([0-9]+,[0-9]+,[0-9]+,[0-9]+),([0-9]+),([0-9]+)\)$#', $ret[0], $matches)) {
$controlIp = str_replace(',', '.', $matches[1]);
$controlPort = intval($matches[2]) * 256 + intval($matches[3]);
$socket = fsockopen($controlIp, $controlPort);
ftp_raw($ftpStream, 'MLSD');
$s = '';
while (!feof($socket)) {
$s .= fread($socket, 4096);
}
fclose($socket);
}
echo ftp_pwd($ftpStream); //line 256
echo ' --> ';
ftp_chdir($ftpStream, $currentFolder); //line 258
echo ftp_pwd($ftpStream); //line 260
显示器:
/ : <br />
<b>Warning</b>: ftp_pwd(): Transfer complete. in <b>/media/sf_web/x/webService/models/Ftp.class.php</b> on line <b>256</b><br />
--><br />
<b>Warning</b>: ftp_chdir(): "/www" is current directory. in <b>/media/sf_web/x/webService/models/Ftp.class.php</b> on line <b>258</b><br />
<br />
<b>Warning</b>: ftp_pwd(): CWD command successful. in <b>/media/sf_web/x/webService/models/Ftp.class.php</b> on line <b>260</b><br />
然后错误不一致。
有关信息,如果我评论整个 "If" 条件块,我会得到正常的行为,没有警告:
/ : /www --> /
*/
我的错误在哪里?如何解释不连贯的警告消息以及之后无法正确使用$ftpStream
?
几个小时以来我一直在寻找解决方案,因此非常感谢您的帮助...:)
提前致谢。
PHP 现在原生支持 MLSD
命令,因为 7.2 带有 ftp_mlsd
function。
原回答:
与所有 FTP 数据传输命令一样,MLSD
发出多重响应。
通常是一个或多个 1xx
初步回复,例如
150 Opening data channel for directory listing of "/path"
最后一个回复,在你的情况下:
226 Transfer complete.
ftp_raw
函数只读取一个响应,即初步 150
一个。保持最终 226
响应 "in queue".
一旦您发出新的 FTP 命令,即 PWD
,它会找到待处理的 226
响应,并在该响应上停止。
实际 PWD
响应再次离开 "in the queue":
257 /www is current directory.
以此类推
您收到警告是因为状态代码与命令不匹配。对 PWD
的正面回应是 257
,而不是 226
。对 CWD
的正面回应是 250
,而不是 257
,等等
恐怕无法同步,因为没有 skip/read FTP 回复的 PHP 功能。
所以您唯一的选择可能是断开连接并重新连接。
我目前在使用 FTP 的 ftp_raw
功能时遇到问题。
我需要获取 FTP 目录的非常精确和详细的文件和目录列表(ftp_rawlist
对日期时间不够精确,因此未指定)。所以我想使用更规范化的命令:MLSD
。
我可以获得我想要的文件列表,但是从套接字中获取数据后,无法再使用 PHP 的 ftp*
功能...
这是我的代码的摘录:
//Current folder = "/"
$directory = "/www/";
$currentFolder = ftp_pwd($ftpStream);
echo $currentFolder;
echo ' : ';
ftp_chdir($ftpStream, $directory);
$ret = ftp_raw($ftpStream, 'PASV');
if (preg_match('#^227.*\(([0-9]+,[0-9]+,[0-9]+,[0-9]+),([0-9]+),([0-9]+)\)$#', $ret[0], $matches)) {
$controlIp = str_replace(',', '.', $matches[1]);
$controlPort = intval($matches[2]) * 256 + intval($matches[3]);
$socket = fsockopen($controlIp, $controlPort);
ftp_raw($ftpStream, 'MLSD');
$s = '';
while (!feof($socket)) {
$s .= fread($socket, 4096);
}
fclose($socket);
}
echo ftp_pwd($ftpStream); //line 256
echo ' --> ';
ftp_chdir($ftpStream, $currentFolder); //line 258
echo ftp_pwd($ftpStream); //line 260
显示器:
/ : <br />
<b>Warning</b>: ftp_pwd(): Transfer complete. in <b>/media/sf_web/x/webService/models/Ftp.class.php</b> on line <b>256</b><br />
--><br />
<b>Warning</b>: ftp_chdir(): "/www" is current directory. in <b>/media/sf_web/x/webService/models/Ftp.class.php</b> on line <b>258</b><br />
<br />
<b>Warning</b>: ftp_pwd(): CWD command successful. in <b>/media/sf_web/x/webService/models/Ftp.class.php</b> on line <b>260</b><br />
然后错误不一致。
有关信息,如果我评论整个 "If" 条件块,我会得到正常的行为,没有警告:
/ : /www --> /
*/
我的错误在哪里?如何解释不连贯的警告消息以及之后无法正确使用$ftpStream
?
几个小时以来我一直在寻找解决方案,因此非常感谢您的帮助...:)
提前致谢。
PHP 现在原生支持 MLSD
命令,因为 7.2 带有 ftp_mlsd
function。
原回答:
与所有 FTP 数据传输命令一样,MLSD
发出多重响应。
通常是一个或多个 1xx
初步回复,例如
150 Opening data channel for directory listing of "/path"
最后一个回复,在你的情况下:
226 Transfer complete.
ftp_raw
函数只读取一个响应,即初步 150
一个。保持最终 226
响应 "in queue".
一旦您发出新的 FTP 命令,即 PWD
,它会找到待处理的 226
响应,并在该响应上停止。
实际 PWD
响应再次离开 "in the queue":
257 /www is current directory.
以此类推
您收到警告是因为状态代码与命令不匹配。对 PWD
的正面回应是 257
,而不是 226
。对 CWD
的正面回应是 250
,而不是 257
,等等
恐怕无法同步,因为没有 skip/read FTP 回复的 PHP 功能。
所以您唯一的选择可能是断开连接并重新连接。