- PR -

service(HttpServletRequest req, HttpServletResponse res)でres.getOutputStreamとres.getWriterの共存

1
投稿者投稿内容
るし
会議室デビュー日: 2004/03/30
投稿数: 4
投稿日時: 2004-03-30 17:35
service(HttpServletRequest req, HttpServletResponse res)でres.getOutputStreamとres.getWriterの共存


いつもお世話になっております、るしです。RedHat9をサーバマシンにして、JavaServletでWebアプリケーションを作成中です。
(JavaとServlet歴2ヶ月、JavaVersion:j2sdk-1_4_1_06 Tomcat4:tomcat4-4.1.19 クライアントマシン:WindowsXPとRedHat9Linux)

・やりたいこと:サーバマシンにあるファイルを複数個ブラウザからダウンロード(ダウンロードダイアログが1つ1つ出る)。

・処理方法:DownTransactionページでPutDownloadData.DataPlace[PutDownloadData.DataDownloadCount][2](どこからでも書き込み呼び出し可能なString変数)にファイル名を入れ、DownPluralページに飛び、DownPluralページでそのファイルをダウンロード(ダウンロードダイアログを出す)し、またDownTransactionページに戻り、別のファイル名を変数に入れる。またDownPluralページに飛びダウンロードし……を繰り返し、変数に入れるファイル名がなくなれば、別のページに飛ばす。

・現状:DownTransactionページからDownPluralページに飛んできて、1つのファイルをダウンロードできる。だが、DownTransactionページに戻らない。「//html表示とJavaScriptでページ移動」部分の処理が動いていないようだ。(ダウンロード後、htmlが表示されない、JavaScriptで飛ばない、「//ログの書き出し」部分が動かないことより判断。)

・以下のソースの「//ファイルをダウンロードする」から「//ファイルダウンロード部分終了」までをコメントアウトすると、「//html表示とJavaScriptでページ移動」部分の処理が正常に動き、ファイルの個数分DownTransactionページとDownPluralページを言ったりきたりしていることがログより判明。

・分からない点:res.getOutputStreamでダウンロード部分を作り、res.getWriterでhtml書き出しを行っているのだが、この二つが共存できていない?


 前置きが長くなってしまいましたが、皆様におたずねしたい点としては、

1)このソースやresの使い方に根本的な間違いがある?
2)res.getOutputStreamでダウンロードする方法以外でダウンロードできない?
3)res.getWriterでhtml書き出し+JavaScriptで飛ぶ以外の方法で別のページに飛ばせない?
4)うまくこの二つを共存させて処理を行う方法はない?
5)何か複数ダウンロードでいい方法はない?

 です。どれかの項目について何とか知恵を拝借できませんでしょうか……?


【DownPlural.java】

import java.sql.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class DownPlural extends HttpServlet{
public void service(HttpServletRequest req, HttpServletResponse res) thows IOException {
//ファイルをダウンロードする。
try{
OutputStream out = res.getOutputStream();
File file = new File(DefineNo.Client_Dir + PutDownloadData.DataPlace[PutDownloadData.DataDownloadCount][2]);
long size = file.length();
FileInputStream in = new FileInputStream(DefineNo.Client_Dir + PutDownloadData.DataPlace[PutDownloadData.DataDownloadCount][2]);
res.setContentLength((int)size);
res.setContentType("application/octet-stream");
res.setHeader("Content-Disposition", "attachment; filename=" + PutDownloadData.DataPlace[PutDownloadData.DataDownloadCount][2]);
int c;
while (( c = in.read() ) != -1){
out.write(c);
}
out.flush();
out.close();
in.close();
//ログとり
LogBuff_download[LogBuffNum_download][1]="OK";
LogBuffNum_download++;

}
catch (IOException ex){
//ログとり
LogBuff_download[LogBuffNum_download][1]="Fail.." + ex;
LogBuffNum_download++;
}
//ファイルダウンロード部分終了

//ログとり
LogBuff_download[LogBuffNum_download][1]="templast" + PutDownloadData.DataDownloadCount;
LogBuffNum_download++;
//html表示とJavaScriptでページ移動
res.setContentType("text/html; charset=EUC-JP");
PrintWriter pw = res.getWriter();
pw.println("<html><body>Downplural");
String[] LocationReplace = new String[4];
LocationReplace = DefineInitialize.JavascriptLocation("DownTransaction",10);
PutDownloadData.DataDownloadCount--;
for (int k=0; k<5; k++){
pw.println(LocationReplace[k]);
}
pw.println("</body></html>");
//ログの書き出し
MakeLog MakeLog_s = new MakeLog();
String flag = MakeLog_s.MakeLogFile(LogBuff_download, LogBuffNum_download);
pw.close();
}
}


【DefineInitialize.JavascriptLocation】
(Timeout×1000秒後に、NewPageに飛ばす処理を行うJavaScript)
static String[] JavascriptLocation(String NewPage, int Timeout){
String[] LocationReplace= new String[5];
LocationReplace[0] = "<script Language=\\"JavaScript\\">";
LocationReplace[1] = "<!--";
LocationReplace[2] = "setTimeout(\\"location.replace('" + NewPage + "')\\" , " + Timeout + ")";
LocationReplace[3] = "// -->";
LocationReplace[4] = "</script>";
return LocationReplace;
}
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-03-30 19:04
>1)このソースやresの使い方に根本的な間違いがある?
httpでは一回のレスポンスでひとつのコンテントしか送信できません
>2)res.getOutputStreamでダウンロードする方法以外でダウンロードできない?
バイナリのデータを送るなら ServletOutputStream を使う方法で間違いありません。
>3)res.getWriterでhtml書き出し+JavaScriptで飛ぶ以外の方法で別のページに飛ばせない?
RequestDispatcher.forward や redirect はいかがでしょう?
>5)何か複数ダウンロードでいい方法はない?
サーバ側で zip にまとめて1ぺんにダウンロードさせるというのはいかがでしょうか?
るし
会議室デビュー日: 2004/03/30
投稿数: 4
投稿日時: 2004-04-01 11:58
インギさま、どうもお答えありがとうございます。

>3)
>RequestDispatcher.forward や redirect はいかがでしょう?

ということで、とりあえず、RequestDispatcher.forwardを使ってみることにしました。

ソース内の
out.flush();
out.close();
in.close();
の下に
RequestDispatcher rd;
rd = req.getRequestDispatcher("DownTransaction");
rd.forward(req, res);
を組み込んでDownTransactionページに飛ばそうとしたのですが、
やはり反応がありません。
これも、resが入っているということは、
>1)
>httpでは一回のレスポンスでひとつのコンテントしか送信できません
に当たってしまい、二度送信しようとしているのでしょうか?

別のServletページに組み込んで使っていたres.sendRedirectも、反応なしです……。
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-04-02 00:26
out.close()をコールした時点で、クライアントへのレスポンスの送信処理が終了してしまいませんか?
るし
会議室デビュー日: 2004/03/30
投稿数: 4
投稿日時: 2004-04-02 17:28
シュンさま、どうもお返事ありがとうございます。
新しくつけたRequestDispatch……部分をclose関連部分の上においてみても、close関連部分を//でコメントアウトしてみても、特に変化は見られませんでした。
reqやresを呼び出し前までしか処理が終了しておらず、飛ばし部分やhtml表示部分まで処理が進みません……。
悶吉
会議室デビュー日: 2004/03/30
投稿数: 14
投稿日時: 2004-04-02 18:11
どうもインギさんやシュンさんのおっしゃってる事が理解出来ていないようですね。
servletAPIドキュメントのgetOutputStreamメソッド・getWriterメソッドの部分はお読みになりましたか?
httpの仕様について調べて見たりしましたか?
るし
会議室デビュー日: 2004/03/30
投稿数: 4
投稿日時: 2004-05-06 13:52
返事がすっかり遅くなりましたが、試行錯誤の結果、インギさんが初めに言われていた、サーバ側で圧縮してダウンロードする方法でシステムを作成しました。

1)ダウンロード可能ファイル一覧表示からチェックボックスでダウンロードしたいデータを選択する
2)FTPで遠いサーバからServlet動作サーバにデータを引っ張ってくる
3)引っ張ったものをZIP圧縮し、Servlet動作サーバに置く。
4)ZIPファイル名を返し、「上記の1つのファイルをダウンロードする方法」を使ってそのZIPファイルをダウンロード

メソッドの部分を読んでもどうもよく理解できませんでした。今回は圧縮を使いましたが、また何とかして複数ダウンロード処理を作っていきたいところです……。
どうも、いろいろとお答えありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)