サーバーにファイルをアップロード(PUT)しようとしているのですが
うまくいきません。
次のようなソースです。
何が悪いのか診断してもらえないでしょうか?
※補足
・FFFTPでは、PASVモード有効、ポート番号21でGETもPUTも成功しているので、
FTPの設定の問題ではないと思います。
・$ftp->pwd()すると、cwdで移動したパスをちゃんと取ってくるので、
ログインや cwdは成功しているようです。
・特に、$ftp->putでパソコン上のファイルのパスを指定する方法がよくわかりません。
use Net::FTP;
$FtpHostName = "hogehoge.com";
$FtpDataPath = "/home/hogehoge/www/sub";
$FtpUserName = "myname";
$FtpPassword = "letmein";
$datafile = "C:\\temp\\test.txt";
$ftp = Net::FTP->new( $FtpHostName );
$ftp -> login( $FtpUserName, $FtpPassword );
$ftp -> pasv();
$ftp -> port( 21 );
$ftp -> ascii();
$ftp -> cwd( $FtpDataPath );
$ftp -> put( $datafile ) or
die "PUT FAILED";
$ftp -> quit();
よろしくお願いします。
「$ftp -> port( 21 );」の行を削除して試してみてください。
このメソッドは、サーバーの21番ポートに接続する事を指定するものではなく、クライアントPCのIPアドレスと待ち受けるポートを送信するもののようです。
http://x68000.q-e-d.net/~68user/net/ftp-4.html
・「ポート番号の伝達」より
・PORT … ポート番号を送信 (Active モード)
データコネクションの確立の際、FTP サーバ側から FTP クライアント側に接続するよう伝える。 FTP クライアントが IP アドレス 10.0.0.1 で動いており、ポート 5000 番を listen しているなら、
PORT 10,0,0,1,19,136
200 PORT command successful.
と送信する (5000=19×256+136)。 その後 FTP クライアントが LIST やRETR コマンドを送信すると、 FTP サーバ側が 10.0.0.1 のポート 5000 に接続し、データの送受信が始まる。
※次のように「$ftp->message」でコマンド実行で返されたメッセージを確認してみてください。
$ftp->pasv(); print $ftp->message . "<br>\r\n";
次のような形式でIPアドレスとポート番号が返されると思います。
Entering Passive Mode (***,***,***,***,242,90).
※上記の場合、242×256+90=62042番ポート
※Activeモードで接続する場合、「$ftp->port()」と何も指定しないで実行してみてください。(「$ftp->port(***,***,***,***,xxx,xx)」と自分のPCのIPとポート番号を指定しても接続できると思いますが、未確認です。)
※Passiveモードで接続するのでしたら、portを実行する必要はありません。
ActiveモードとPassiveモードの違いは、次のページも確認しておくとより理解できると思います。
http://x68000.q-e-d.net/~68user/net/ftp-3.html
※(1)から読んでもいいと思います
「Active モード」というもので、データコネクションの確立の際、「FTP サーバ側が能動的に FTP クライアント側に接続する」という動作になります。
一方、「Passive モード」というものがあります。このモードでは、「FTP サーバ側が受け手となり、FTP クライアントからの接続を待つ」という動作になります。つまり、FTP クライアントは、 bind・listen・accept などのサーバ的な動作をする必要がなくなるのです。
あるいは、オプションで次のように指定しても、すべての転送がPassiveモードになるようです。
$ftp = Net::FTP->new($FtpHostName, Passive => 1);
http://perldoc.jp/docs/modules/libnet-1.12/Net/FTP.pod
Passive - 0以外の値を設定すると、全てのデータ転送はパッシブモードを使って行われます。いくつかのダム(dumb)サーバーといくつかのファイアウォールの設定を除けば、通常、必要とされません。これは環境変数FTP_PASSIVEによって設定することもできます。
とても詳しい解説をありがとうございます!
「$ftp -> port( 21 );」を削除しただけではうまくいかなかったので、
教えてもらった内容をじっくり理解して、いろいろ試してみようと思います。
結果は後ほど追記させてもらいます。
ありがとうございました!
■追記
報告が遅くなってすいません。
いろいろやってみたのですが、やはりアップロード(PUT)はうまくいきませんでした。
そこで試しに サーバー上のファイル "test.txt" をダウンロードしようと
下記方法で GETをしてみたところ、
$ftp -> get( "test.txt", "C:\\temp\\test.txt" )
なんと、"test.txt"が パソコンの "C:\temp\"フォルダにコピーされるのではなく、
サーバーのカレントディレクトリに "C:\temp\test.txt"というファイル名の
ファイルが1個コピーされました。
どうやら、Net::FTPは、サーバーとローカルPC間の FTP通信を行ってくれる
モジュールではないようです。
Net::FTPモジュールを使うのはやめて、別の方法でファイルをアップロードすることに
します。
お世話をかけて申し訳ありませんでした。
Net::FTPモジュールの問題は解決できませんでしたが、rouge_2008さんの回答で
今までなんとなく使っていたFTPについての理解が深まりました。
丁寧な回答をありがとうございました!