Monthly Archives: 4月 2011

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

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

なぜか。

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

実行したソースコード

  1. <?php
  2.  
  3. //ftp接続設定
  4. $baseUrl = "ftp://hoge:foobar@127.0.0.1/";
  5. $path = "/var/www/html/index.html";
  6.  
  7. //テンポラリファイル準備
  8. $fp = tmpfile();
  9. $fpe = tmpfile();
  10.  
  11. //curlに設定をセット
  12. $options = array(
  13. CURLOPT_QUOTE => array("CWD " . dirname($path)),
  14. CURLOPT_URL => $baseUrl . basename($path),
  15. CURLOPT_FILE => $fp,
  16. CURLOPT_VERBOSE => true,
  17. CURLOPT_STDERR => $fpe,
  18. );
  19.  
  20. //curl実行
  21. $ch = curl_init();
  22. curl_setopt_array($ch, $options);
  23. curl_exec($ch);
  24. curl_close($ch);
  25.  
  26. fclose($fp);
  27.  
  28. //ログ表示
  29. rewind($fpe);
  30. echo stream_get_contents($fpe);

成功するパターン

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してやがる・・・・!!
どおりでダウンロードできないわけね。

解決策探したけれど、中々解決できなかったので妥協して下記のようにした。

  1. $options = array(
  2. CURLOPT_QUOTE => array("CWD " . dirname($path)),
  3. CURLOPT_URL => $baseUrl . basename($path),
  4. CURLOPT_FILE => $fp,
  5. CURLOPT_FRESH_CONNECT => true,
  6. );

CURLOPT_FRESH_CONNECTをtrueにすると、接続を保持せず再接続するみたい。
新規接続時はCWDが正常に動くので、とりあえずこれで。

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

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