/

PHP FTP 间歇性无法上传文件

2020-04-23 后记:疑似是前置的负载均衡服务器有问题,改为直接使用真实 IP 后问题消失。


PHP Warning:  ftp_put(): php_connect_nonb() failed: Operation now in progress (115) in ...

环境 PHP 5.6.40。在开发过程中遇到了一个很诡异的情况,在使用 FTP 函数上传文件时,会间歇性无法上传文件。找了几圈有说是 PHP bug、有说是防火墙,都不解决问题。

最后找到了一篇 Why is my PHP script intermittently unable to upload a file via FTP? | stackoverflow 解了大急。(当搜索结果没有找到答案时,可以考虑换几个相近的词再试试)

解决方法:进行循环调用尝试。

// 尝试 5 次
$uploaded = false;
$tries = 0;
while (!$uploaded && $tries <= 5) {
++$tries;
$conn = ftp_ssl_connect($host, $port, 10) or die('FTP服务器连接失败');
//登陆(通过用户名或者匿名登陆)
$result = ftp_login($conn, $user, $password);
if (!$result) {
ftp_close($conn);
die('ftp_login 失败');
}

ftp_set_option($conn, FTP_USEPASVADDRESS, false);

// turn passive mode on
ftp_pasv($conn, true);

$success = ftp_put($conn, $remoteFile, $localFile, FTP_BINARY);
if ($success) {
$uploaded = true;
dump("ftp upload: $success, $remoteFile, $localFile");
} else {
dump("ftp upload failed, tries: $tries");
}

ftp_close($conn);
}

循环 try 第二次就成功了,不知为啥。PHP の FTP(S)通信で php_connect_nonb() failed: Operation now in progress (115) | qiita 这篇文章有分析,读后还是不太清楚,望有缘人来指导。

どうやら Operation now in progress (115)は EINPROGRESS から来ているらしい。常に非同期で connect するため最初の connect で EINPROGRESS が帰るのは正常だが、asynchronous=true の場合その後同期処理のために poll で接続完了を待つ。だが poll はエラーが起きても errno を更新しないため、接続に失敗したとき errno=EINPROGRESS の状態で返ってしまっているように見える。

– EOF –