Javaの道 Javaに関する
 ニュースJava基本Servlet・JSPオープンソースFAQ掲示板
Javaの道 >  掲示板 >  掲示板(FTPクライアントのServlet化)
閲覧数:1013
掲示板(FTPクライアントのServlet化)
名前
題名 FTPクライアントのServlet化
質問内容

質問を評価する
(0ポイント)
お世話になります。
引き続き同じ話題になりますが、宜しくお願いします。

Java で HelloWorld さんのサンプルFTPを参考に受信用プログラムを作成しました。
勿論、ファイルの受信は出来ています。
ですがServlet化したとたん、接続と受信のほうは出来ますが肝心のファイル自体が作成されません。
以前こちらに似たような記事(送信)が書かれていましたが、当方の場合0バイトファイルすら作られない上体です。
Servlet化したと書きましたが、内容は設定値を getParameter でとってくるような形にし、実行後 printWriter で終了画面を作るといった挙動を追加したのみです。
(その他細かい request 等もあります)

気になる部分はダウンロードを行うソース部分ですが、何かJavaとservletでは記述方法が違ったりするんでしょうか?
長くなりましたが、お分かりになられる方いらっしゃいました羅よろしくお願いします

以下ソースとTinyFtpdのログです

ソース:
package ftp;

import java.io.*;
import java.net.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      try {

    // 値取得
    String host = request.getParameter("address");
    String loginName = request.getParameter("user");
    String password = request.getParameter("pass");
    String dirName = request.getParameter("path");
    String fileName = request.getParameter("file");

    // 接続します
    ctrlSocket = new Socket(host, CTRLPORT);
    localHostAddress = ctrlSocket.getLocalAddress().getAddress();
    ctrlOutput = new PrintWriter(ctrlSocket.getOutputStream());
    ctrlInput = new
    BufferedReader(new InputStreamReader(ctrlSocket.getInputStream()));

    // FTP 接続を開始
    ctrlOutput.println("USER " + loginName);
    System.out.println("USER " + loginName);
    ctrlOutput.flush();
    ctrlOutput.println("PASS " + password);
    System.out.println("PASS " + password);
    ctrlOutput.flush();
    ctrlOutput.println("CWD " + dirName);
    System.out.println("CWD " + dirName);
    ctrlOutput.flush();
    ctrlOutput.println("TYPE I");
    System.out.println("TYPE I");
    ctrlOutput.flush();

    // ダウンロードを開始
    FileOutputStream fos = new FileOutputStream(fileName);
    Socket dataSocket = dataConnection("RETR " + fileName);
    BufferedInputStream instr = new BufferedInputStream(dataSocket.getInputStream());
    int n;
    byte[] buff = new byte[1024];
    while ((n = instr.read(buff)) > 0) {
      fos.write(buff,0,n);
    }
    dataSocket.close();
    fos.close();

    // FTP 接続をクローズ
    ctrlOutput.close();
    ctrlInput.close();
    ctrlSocket.close();
  } catch (Exception e) {
    e.printStackTrace();
  }

  // ContentTypeを設定
  response.setContentType("text/html; charset=Shift_JIS");
  // 出力用PrintWriterを取得
  PrintWriter pw = response.getWriter();
  pw.println("<html><head>");
  pw.println("<title>FTP結果画面</title>");
  pw.println("</head><body bgcolor=\"#000000\" text=\"#ffffff\">");
  pw.println("ダウンロードが完了しました<br><br>");
  pw.println("ダウンロードされたファイルは、アプリケーションインストールディレクトリ配下の「FTPServlet」 内です");
  pw.println("</body></html>");

}

/**
* データ送受信用ソケットを取得します
*/
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;
  }
}



TinyFtpログ:
/shinobu//OK/ 192.168.12.10から接続要求がありました
/shinobu/USER/OK/ パスワードを要求します
/shinobu/PASS/OK/ ログインしました。
/shinobu/CWD/OK/ ディレクトリがC:\test\になりました
/shinobu/TYPE/OK/ バイナリモードに入ります
/shinobu/PORT/OK/ データリンクをクローズしました
/shinobu/PORT/OK/ アドレス192.168.12.10 ポート 1333に接続しました
/shinobu/RETR/OK/ C:/shinobu/test/FtpText.txt(Bin)の送信準備が出来ました
/shinobu/RETR/OK/ C:/shinobu/test/FtpText.txt(8037Bytes)の読み込みが完了しました
/shinobu/RETR/OK/ C:/shinobu/test/FtpText.txt(8037Bytes)の送信が完了しました
/shinobu/RETR/OK/ データリンクをクローズしました
/shinobu/RETR/NG/ ユーザーから切断されました
質問日時 2007-02-16 11:03:17
名前
mio
回答内容

回答を評価する
(0ポイント)
>何かJavaとservletでは記述方法が違ったりするんでしょうか?
ServletもJavaなんですが…。

えーと、どこまでできているのかとか、デバッグは入れてみたんでしょうか。
Servletに直したらできなかった、だから質問という前に、なにかできることをやってみてください。
とりあえず、try〜catchの使い方が変です。

>String host = request.getParameter("address");

こんなところでExceptionは発生しますか?
回答日時 2007-02-16 12:24:25
名前
回答内容

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

ありがとうございます。
JavaとServletをわざとわけて書いた理由については、Javaコマンドで実行するとできるが、Tomcatに乗せられるよう変更して実行すると失敗します・・・という意味でした。
分かりづらくてすいません。

当方で出来るデバッグとして、以下のようにソースを修正しました。

  // ダウンロードを開始
  System.out.println("ダウンロード開始");
  FileOutputStream fos = new FileOutputStream(fileName);
  System.out.println(fos);
  Socket dataSocket = dataConnection("RETR " + fileName);
  System.out.println(dataSocket);
  BufferedInputStream instr = new BufferedInputStream(dataSocket.getInputStream());
  System.out.println(instr);

  int n;
  System.out.println("1");
  byte[] buff = new byte[1024];
  System.out.println("2");
  while ((n = instr.read(buff)) > 0) {
    System.out.println(n);
    fos.write(buff,0,n);
    System.out.println(fos);
  }
  System.out.println("書き込み終了");
  dataSocket.close();
  fos.close();

  // FTP 接続をクローズ
  ctrlOutput.close();
  ctrlInput.close();
  ctrlSocket.close();

このソースで、ソケットクローズまですべての文章が出力されました

ダウンロード開始
java.io.FileOutputStream@1313906
Socket[addr=/192.168.12.10,port=2069,localport=2068]
java.io.BufferedInputStream@96cf11
1
2
1024
java.io.FileOutputStream@1313906
1024
java.io.FileOutputStream@1313906
1024
java.io.FileOutputStream@1313906
1024
java.io.FileOutputStream@1313906
1024
java.io.FileOutputStream@1313906
1024
java.io.FileOutputStream@1313906
1024
java.io.FileOutputStream@1313906
869
java.io.FileOutputStream@1313906
書き込み終了

途中で止まることなく最後まで処理されているみたいです。

>try〜catch
おかしかったですか・・・もう少し考えて見ます

>こんなところでExceptionは発生しますか?
これについても、特にログには出力されないんです。
それとも何か違う方法で確認しなきゃならないものなのでしょうか。
回答日時 2007-02-16 13:08:33
名前
回答内容

回答を評価する
(0ポイント)
>接続と受信のほうは出来ますが肝心のファイル自体が作成されません。
どこにできることを期待していますか、どこかに出来ていませんか?

mioさんが言われるようにデバッグ文をいれて確認しましょう。

あと、ログを見ると送信完了のメッセージが有りません。
>/shinobu/RETR/NG/ ユーザーから切断されました
途中で切断されている可能性があります。
Servletでない方のログにも送信完了のログが無ければ受信したファイルは完全でないかもしれません。
完全でない場合、TinyFtpは動作ウエイトの設定があるので、最小にすれば間に合うかもしれませんが・・
根本的にはFTPのレスポンスコードを受け取って切断するようにして下さい。

切断前にはQUITを送ってやりましょう、でないといつまでも
>/shinobu/RETR/NG/ ユーザーから切断されました
がでます。
回答日時 2007-02-16 13:18:53
名前
回答内容

回答を評価する
(0ポイント)
tama さん
ありがとうございます。

結果としては、対象ファイルが見つかりました。
理由はわからないんですが、状況を書かせていただきます。
当方、Eclipseにて開発を行っています。
クラスの作成にて実行したJavaファイルは、プロジェクト配下に対象ファイルが受信されていました。
その為、Servletで作成した場合も同じ場所に受信されると考えていたんですが、なぜかeclipse.exeと同じ場所に保管されていました。

きちんと受信はされていたようです・・・がどうも解せないというか・・・。
指定する方法があれば指定したほうがいいかもしれませんが、結果として受信だけは出来たのでひと段落といった感じです。

>FTP結果判断
FTPコマンドの返り値は getLastStatusCode で取得するものだと思いますが、加える部分は

>while ((n = instr.read(buff)) > 0) {〜

 の後というので間違いありませんか?
実際に追加して見ようと思います。

>QUIT
ソースに加えたところ、NGが出なくなりました。
ありがとうございます。
回答日時 2007-02-16 14:00:58
名前
回答内容

回答を評価する
(0ポイント)
getLastStatusCode の一文は無かったことに・・・
大いなる勘違いをしてそうな気がしてきました
回答日時 2007-02-16 14:17:03

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



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