PHP+cURLでFTP接続し、CWDすると失敗することがある
諸所の理由でPHP+cURLでFTPダウンロードしてたのですが、 サーバ環境によってはCWDがうまいこといかないみたい;;
なぜか。
詳細ログをとってFTPコマンドのやり取りを解析してみた。
//ftp接続設定 $baseUrl = "ftp://hoge:foobar@127.0.0.1/"; $path = "/var/www/html/index.html";
//テンポラリファイル準備 $fp = tmpfile(); $fpe = tmpfile();
//curlに設定をセット $options = array( CURLOPT_QUOTE => array("CWD " . dirname($path)), CURLOPT_URL => $baseUrl . basename($path), CURLOPT_FILE => $fp, CURLOPT_VERBOSE => true, CURLOPT_STDERR => $fpe, );
//curl実行 $ch = curl_init(); curl_setopt_array($ch, $options); curl_exec($ch); curl_close($ch);
fclose($fp);
//ログ表示 rewind($fpe); echo stream_get_contents($fpe);[/php]
成功するパターン
1度目の接続
* About to connect() to 127.0.0.1 port 21 (#0) * Trying 127.0.0.1... * connected * Connected to 127.0.0.1 (127.0.0.1) port 21 (#0) < 220 ProFTPD 1.3.3 Server (ProFTPD) [127.0.0.1] > USER hoge < 331 Password required for foo. > PASS foobar < 230 User foo logged in. > PWD < 257 "/home/hoge" is current directory. * Entry path is '/home/hoge' > CWD /var/www/html < 250 CWD command successful ...
2度目の接続
* Re-using existing connection! (#0) with host 127.0.0.1 * Connected to 127.0.0.1 (127.0.0.1) port 21 (#0) * Request has same path as previous transfer > CWD /var/www/html < 250 CWD command successful ...
失敗するパターン
1度目の接続
* About to connect() to 127.0.0.1 port 21 * Trying 127.0.0.1... * connected * Connected to 127.0.0.1 (127.0.0.1) port 21 < 220 ProFTPD 1.3.3 Server (ProFTPD) [127.0.0.1] > USER hoge < 331 Password required for foo. > PASS foobar < 230 User foo logged in. > PWD < 257 "/home/hoge" is current directory. * Entry path is '/home/hoge' > CWD /var/www/html < 250 CWD command successful ...
2度目の接続
* Re-using existing connection! (#0) with host 127.0.0.1 * Connected to 127.0.0.1 (127.0.0.1) port 21 > CWD /var/www/html < 250 CWD command successful > CWD /home/hoge < 250 CWD command successful ...
ログ見て、一目瞭然っすね。 CURLOPT_QUOTEでせっかくCWDしたのに、こいつ、ホームディレクトリに再度CWDしてやがる・・・・!! どおりでダウンロードできないわけね。
解決策探したけれど、中々解決できなかったので妥協して下記のようにした。 [php]$options = array( CURLOPT_QUOTE => array("CWD " . dirname($path)), CURLOPT_URL => $baseUrl . basename($path), CURLOPT_FILE => $fp, CURLOPT_FRESH_CONNECT => true, );[/php]
CURLOPT_FRESH_CONNECTをtrueにすると、接続を保持せず再接続するみたい。 新規接続時はCWDが正常に動くので、とりあえずこれで。
とはいえ何度もログインしてて非常に美しくないので、もし解決策知ってる方がいたら教えてください!><