Javaの道 Javaに関する
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道 >  掲示板 >  掲示板(FTPサーバへの転送プログラム)
閲覧数:2348
掲示板(FTPサーバへの転送プログラム)
名前
ayu
題名 FTPサーバへの転送プログラム
質問内容

質問を評価する
(0ポイント)
FTPサーバはTiny FTP Daemonをたてました。

プログラムは
import java.io.*;
import java.net.*;

public class FTP {
  private static final int CTRLPORT  = 21; // ftpの制御用のポート
  private static Socket ctrlSocket; // 制御用ソケット
  private static PrintWriter ctrlOutput; // 制御出力用ストリーム
  private static BufferedReader ctrlInput; // 制御入力用ストリーム
  private static byte[] localHostAddress; // ローカルホストのアドレス

  public static void main(String[] args) {
    try {
      /** 設定してください **/
      String host = "IPアドレス";
      String loginName = "ユーザ名i";
      String password = "パスワード";
      String dirName = "/ディレクトリ場所/";
      String fileName = "転送したいファイル名t";

      // 接続します
      ctrlSocket = new Socket(host, CTRLPORT);
      localHostAddress = ctrlSocket.getLocalAddress().getAddress();
      ctrlOutput = new PrintWriter(ctrlSocket.getOutputStream());
      ctrlInput = new 
        BufferedReader(new InputStreamReader(ctrlSocket.getInputStream()));
      // ユーザー認証します
      ctrlOutput.println("USER " + loginName);
      ctrlOutput.flush();
      ctrlOutput.println("PASS " + password);
      ctrlOutput.flush();
      // 指定したディレクトリに移動します
      ctrlOutput.println("CWD " + dirName);
      ctrlOutput.flush();
      // バイナリモードに設定します(アスキーモードの場合は'TYPE A')
      ctrlOutput.println("TYPE I");
      ctrlOutput.flush();
      // アップロードします
      FileInputStream fis = new FileInputStream(fileName);
      Socket dataSocket = dataConnection("STOR " + fileName);
      OutputStream outstr = dataSocket.getOutputStream();
      int n;
      byte[] buff = new byte[1024];
      while ((n = fis.read(buff)) > 0) {
        outstr.write(buff,0,n);
      }
      dataSocket.close();
      fis.close();

      // 接続を閉じます
      ctrlOutput.close();
      ctrlInput.close();
      ctrlSocket.close();
    }catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * データ送受信用ソケットを取得します
   */
  private static Socket dataConnection(String ctrlcmd) 
      throws IOException,UnknownHostException {
    String cmd = "PORT ";
    ServerSocket serverDataSocket = new ServerSocket(0,1);
    for (int i=0;i<4;i++) {
      cmd = cmd + (localHostAddress[i] & 0xff) + ",";
    }
    cmd = cmd + (((serverDataSocket.getLocalPort())/256) & 0xff)
              + ","
              + (serverDataSocket.getLocalPort() & 0xff);

    ctrlOutput.println(cmd);
    ctrlOutput.flush();
    ctrlOutput.println(ctrlcmd);
    ctrlOutput.flush();

    Socket dataSocket = serverDataSocket.accept();
    serverDataSocket.close();
    return dataSocket;
  }
}
 
サーバにはファイルが作られるのですが、中身が転送できません。
空のファイルになってしまいます。

また、ログ表示は
/ユーザ名/USER/OK/ パスワードを要求
/ユーザ名/PASS/OK/ ログインしました
/ユーザ名/CWD/OK/ ディレクトリが**になりました
/ユーザ名/TYPE/OK/ バイナリモードに入ります
/ユーザ名/PORT/OK/ データリンクをクローズしました
/ユーザ名/PORT/OK/ アドレス0.0.0.0 ポート1309に接続しました
/ユーザ名/STOR/OK/ ファイルを受信します
/ユーザ名/STOR/OK/ データリンクをクローズしました
/ユーザ名/STOR/NG/ ユーザーから切断させました

と出ます。

データを転送したいのですが、どうしたらいいのかわかりません。
ささいなことでもいいので、よろしくお願いします。
質問日時 2006-12-28 16:03:18
名前
回答内容

回答を評価する
(0ポイント)
このプログラムは
http://www.hellohiro.com/ftp.htm
のサンプルですよね。

このサンプルはFTPの応答コードを受信していないので、ファイルの転送が完了していないのにソケットをクローズする可能性があります。
FTPサーバにもよるのでしょうが、多分それでファイルが転送できないのでしょう。

FTPの制御用ポートから応答コードを受け取るように修正が必要だと思います。

このサンプルだと
ctrlSocketからInputStreamを取得して各応答コードを分析します。
226が転送完了なので、それをチェックすればいいはずです。

手っ取り早くやりたい場合は、アップロード直前にInputStreamからこれまでの応答をすべてreadして、InputStreamを空っぽにしてやります。
ファイルのwriteが終わったら、dataSocket.close()で転送完了になるので。
この後InputStreamでreadすれば、FTPサーバから返事がくるまで待つはずです。
その後に接続を閉じればちゃんと転送できると思います。

ちゃんとしたFTPクライアントが作りたい場合RFCを読まないといけません。
回答日時 2006-12-28 20:45:40
名前
ayu
回答内容

回答を評価する
(0ポイント)
tamaさん

早速の回答ありがとうございます。
http://www.hellohiro.com/ftp.htmのサンプルです。
私はjavaをかじりはじめたばっかりで、このサンプルのプログラムも完璧に理解できていません。
説明していただいたプログラムがあればうれしいのですが、ありませんでしょうか?

よろしくお願いします。

回答日時 2006-12-30 10:29:21
名前
回答内容

回答を評価する
(0ポイント)
>ayuさん

プログラムはありません、以前仕事でFTPクライアントを作った経験から、ソースを見て判断しただけです。

FTPクライアントが必要な目的は何でしょうか?
単にファイルを転送したいだけなら、FTPクライアントはたくさんあるので、それを使えばいいだけだと思いますが。

Javaを使ったFTPの勉強あるいは仕事であるのであれば、自分で理解して手を加えるなり、新たに作るなりしないと意味がないと思います。
それが仕事ともなれば、中身がわからなければサポートも出来ません(仕事であれば仕様書があるでしょうけど・・)

http://hp.vector.co.jp/authors/VA002682/rfc959j.htm
このリンク先はRFC959の文書になっています。
FTPクライアントを作りたい場合、プログラムを作るよりも前に、この内容を把握しておかなければなりません。
私が先に示した内容はヒントでしかありません、あのように修正すればとりあえず1個ファイルが転送できるというだけです。

まずFTPを理解して、仕様を固めてからその仕様を満たすためのJavaのAPIを調べるところから始めてはいかがでしょうか?

そのサンプルプログラムでFTPサーバをIISにしたところ正常にファイルを転送することが出来ました。
ayuさんの目的にもよりますが、FTPサーバを変えるという方法もあるかもしれません、ただこのサンプルはあくまでサンプルであり通常使うには危険です。

>私はjavaをかじりはじめたばっかりで
勉強目的であれば、もう少し簡単な物から手をつけることをおすすめします。
回答日時 2006-12-30 13:02:18
名前
回答内容

回答を評価する
(0ポイント)
忘れてました
org.apache.commons.net.ftp.FTPClient
という、FTPクライアントを実装したものも有るようです。
これを使う方法も有るかもしれません。
回答日時 2006-12-30 13:07:50
名前
ayu
回答内容

回答を評価する
(0ポイント)
tamaさん

そうですよね。自分でももう少し学習をするべきでした。いただいたヒントを元に学習したいと思います。ありがとうございます。

目的は、自分が作成したファイルをプログラムで自動転送できる環境を作りたいと考えています。
回答日時 2006-12-30 19:05:47

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。



このページのトップへ
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道_CopyrightJavaの道