- PR -

JSPを使ってFileをDownloadするには?

投稿者投稿内容
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2002-06-24 21:16
>ダウンロード用出力にJSPWriterではなくjavax.servlet.ServletOutputStream
>を使えばいいのでは??

いえ、JSPWriter を作るときに、getWriter で OutputStream につながった out を作っちゃって、そこにすでに「Content-Type:application/octet-stream」を出力しちゃってるような気がするので、getOutputStream なりをしようとすると Exception 吐いちゃうんじゃないですかね。

内部的には、

JSPWriter out = new JSPWriter(
new OutputStreamWriter(request.getOutputStream()));

みたいなことをしてるはずで、request.getOutputStream() は一度しか使えないはずなんで。

コンテナの実装によっては buffer を破棄して…とかやってくれるかもしれませんが…。

# やっぱ Servlet のほうがいいよなぁ…
Kluger
会議室デビュー日: 2002/06/22
投稿数: 6
お住まい・勤務地: 大阪
投稿日時: 2002-06-24 23:06
Klugerです。みなさん、いろいろありがとうございます。

結局、JSPってのは無理なのかな?コンテンツサイズを指定したりとか
いろいろ試してみましたが結果は同じでした。

とりあえずJSPを使わずServletで逃げることにしましたが....
不思議なんですよね。二回目は成功するんですよ。
なんなんでしょうねぇ...
おがわ
大ベテラン
会議室デビュー日: 2001/08/01
投稿数: 199
お住まい・勤務地: 千葉県
投稿日時: 2002-06-25 01:10
JSP は、もともと、テキスト形式のコンテンツを対象にしています。
画像といったバイナリ形式のコンテンツは Servlet を使って実装すべきです。
Kluger
会議室デビュー日: 2002/06/22
投稿数: 6
お住まい・勤務地: 大阪
投稿日時: 2002-06-25 04:29
早朝プログラマーのKlugerです。(けして総長ではありません )

引用:

謎の白覆面さんの書き込み (2002-06-25 01:10) より:
JSP は、もともと、テキスト形式のコンテンツを対象にしています。
画像といったバイナリ形式のコンテンツは Servlet を使って実装すべきです。



みなさん、ご助言ありがとうございました。
やはり、Servletで実装すべきとのことでそうしたいと思います。
Paul
ベテラン
会議室デビュー日: 2002/04/30
投稿数: 75
お住まい・勤務地: 東京
投稿日時: 2002-06-25 10:19
>やはり、Servletで実装すべきとのことでそうしたいと思います。
その方が問題が少ないとは思いますが、今回の件はそれが原因ではないように思います。

JSP自体は問題ないと思います。
たとえば、以下のように既存のファイルに対して実行すれば、問題なく出力されるはずです。
<%@ page contentType="image/gif" import="java.io.*" %><%

String data_path = "c:\\tmp\\";
String data_name = "test.gif";

response.setHeader("Content-Disposition","attachment; filename="+data_name);
response.setHeader("Content-Description","file download test");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(data_path + data_name));

int x;
while((x=in.read()) >= 0){
out.write(x);
}
in.close();
out.flush();
%>

DloadBeansで、動的にファイルを生成していませんか? そうだとすれば、
> 一回目のリクエストではFileが出来きれていないの?って感じかなぁと思うのですが、
という可能性があります。

リクエストを最初に受けるコントローラで、DloadBeansのプロパティをセットして、当該JSPにForwardしているのであれば、コントローラ側でファイル生成完了のイベントを監視してForwardのタイミングを制御するか、または、ファイル生成完了までDloadBeansのプロパティーのセッタからの戻りを遅延させるなどの方法が考えられます。

K.Nakagome mailto:nakagome@nakagome.co.jp

[ メッセージ編集済み 編集者: nakagome 編集日時 2002-06-25 10:28 ]
asip
ベテラン
会議室デビュー日: 2001/12/27
投稿数: 77
投稿日時: 2002-06-25 18:46
引用:

しょむさんの書き込み

いえ、JSPWriter を作るときに、getWriter で OutputStream につながった out を作っちゃって、そこにすでに「Content-Type:application/octet-stream」を出力しちゃってるような気がするので、getOutputStream なりをしようとすると Exception 吐いちゃうんじゃないですかね。

内部的には、

JSPWriter out = new JSPWriter(
new OutputStreamWriter(request.getOutputStream()));

みたいなことをしてるはずで、request.getOutputStream() は一度しか使えないはずなんで。

コンテナの実装によっては buffer を破棄して…とかやってくれるかもしれませんが…。

# やっぱ Servlet のほうがいいよなぁ…



下記のコードがTomcat4.0にて動作し、ダウンロードもできました。「aa.bb」というファイルと
「C:\\java\\Tomcat4.0\\webapps\\asip\\」は適当です。
「java.lang.IllegalStateException: このレスポンスに対してgetOutputStream()はすで
に呼び出されています」という例外がログに吐かれますが、警告みたいなもので、動作
上、特に問題はないように思います。

コード:
<%@ page contentType="application/octet-stream" import="java.io.*,javax.servlet.*" %>
<%
  String data_path = "C:\\java\\Tomcat4.0\\webapps\\asip\\";
  String data_name = "aa.bb";

  response.setHeader("Content-Disposition","attachment; filename="+data_name);
  response.setHeader("Content-Description","file download test");
  BufferedInputStream in = new BufferedInputStream(new FileInputStream(data_path + data_name));

	ServletOutputStream out2 = response.getOutputStream();

  int x;
  while((x=in.read()) >= 0){
    out2.write(x);
  }
  in.close();
 out2.flush();
  out2.close();
%>

しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2002-06-25 20:48
>「java.lang.IllegalStateException: このレスポンスに対してgetOutputStream()はすで
>に呼び出されています」という例外がログに吐かれますが、警告みたいなもので、動作
>上、特に問題はないように思います。

動作に支障なくても、それはたまたまでは。
例外を吐きながら動くものなんて論外かと。

ServletAPI spec、javadoc にも IllegalStateException が出たときにどうすべきかは明記されていませんから(どこかにある?)、これが出たときに 500 を返すコンテナがあってもおかしくないし、それ以降の処理が中断されても文句はいえないでしょうし。
asip
ベテラン
会議室デビュー日: 2001/12/27
投稿数: 77
投稿日時: 2002-06-25 21:07
引用:

しょむさんの書き込み (2002-06-25 20:48) より:

動作に支障なくても、それはたまたまでは。
例外を吐きながら動くものなんて論外かと。

ServletAPI spec、javadoc にも IllegalStateException が出たときにどうすべきかは明記されていませんから(どこかにある?)、これが出たときに 500 を返すコンテナがあってもおかしくないし、それ以降の処理が中断されても文句はいえないでしょうし。



確かにサーブレットコンテナによっては例外発生後、処理を中断するかもしれませんね。
「例外を吐きながら動くものなんて論外かと」とまで目くじらをたてるほどの処理でも
ないとは思います。システムのメインとなる処理の途中で例外を発生させたまま、放置し
ているのなら、大問題ですが...。十分なテストをして問題が出なければ、この方法でも
構わないと思う方もいらっしゃるかもしれません。別にこの方法を推奨しているわけでは
ありません。

ちょっとした変更でIllegalStateExceptionが出なくなりました。


[ メッセージ編集済み 編集者: asip 編集日時 2002-06-25 23:35 ]

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