人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Perlで、Net::FTPモジュールを使って
サーバーにファイルをアップロード(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();

よろしくお願いします。

●質問者: uta_at_home
●カテゴリ:ウェブ制作
✍キーワード:ASCII FFFTP FTP HOME LOGiN
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● rouge_2008
●200ポイント ベストアンサー

「$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についての理解が深まりました。

丁寧な回答をありがとうございました!

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ