Dabits

サーバサイドから運営まで何でもやるエンジニア系DJ

PHP+cURLでFTP接続し、CWDすると失敗することがある

諸所の理由でPHP+cURLFTPダウンロードしてたのですが、 サーバ環境によってはCWDがうまいこといかないみたい;;

なぜか。

詳細ログをとってFTPコマンドのやり取りを解析してみた。

実行したソースコード [php]<?php

//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が正常に動くので、とりあえずこれで。

とはいえ何度もログインしてて非常に美しくないので、もし解決策知ってる方がいたら教えてください!><

参考 PHP + cURL : さくらインターネットの FTPES でダウンロード