- - PR -
Servlet ファイルダウンロードを実現する際のメモリ占有
1
| 投稿者 | 投稿内容 |
|---|---|
|
投稿日時: 2005-01-26 15:54
Servlet でファイルのダウンロードを実現する手法として,
doPost で Response の OutputStream にファイルを読み込んだバイトデータを そのまま書き込む方法があります。 この方法で大きなファイルをOutputStream書き込んだ場合は, メモリをその分占有してしまうのでしょうか。 また,クライアント側には, ファイルの全データをStreamにすべてのデータを書込み終え, doPostの実行が終了した段階でResponse が返るのでしょうか。 書き方が荒っぽくて恐縮ですが, おそらくStreamに流したデータがどこにストアされ, どのようなタイミングで開放されるのかが よく理解できていないのだと思います。 どなたかご教示いただけましたら助かります。 |
|
投稿日時: 2005-01-26 16:27
レスポンスに書き込んだデータはある程度バッファに溜めてから送信されます。
出力するファイルのサイズだけヒープを占有してしまう、ということはありませんのでご安心ください。 詳しくは仕様書や API の ServletResponse#getBufferSize()/setBufferSize()/commit() あたりをご覧ください。 |
|
投稿日時: 2005-01-27 11:55
インギさん,ご回答ありがとうございました。
APIドキュメントを早速読んでみました。が・・・ すみません,まだ腑に落ちていません。 作成したサンプルでは, ServletResponse の OutputStream に対して, ファイル内容を一気に書き込みます。 そして,書き込み終わると,はじめてdoPostを抜けます。 クライアントは,ブラウザではなくDelphiで作成したアプリです。 HTTP通信を行うコンポーネントを使用してServletに対してPostしてます。 // Delphiコードですみません,HTTPは通信を行うオブジェクト, // response はストリームです Http.Post(url, param, response); この呼び出しが返り次第,responseからデータを受け取っていくのですが, Servlet側でdoPostを抜けない限り,この呼び出しも戻りません。 つまり,ファイルのデータをすべてストリームに入れた時点で, はじめて受信が開始されることになります。 この場合,やはりファイルデータがすべてメモリに展開されてしまうことに なるように思うのです。 別スレッドを使ってdoPostをすぐ抜けるようにしてしまえばいいのでしょうか。 ただ,その場合も,ファイルデータをストリームに書き込んでいく (自分で書いた)処理と, 受信・送信処理が同期を取っているのではないわけですから, たとえば受信が遅れた場合,やはりメモリにデータが積みあがっていくような 気がします。 このあたりをどこか根本的に勘違いしているのでしょうか・・・ |
|
投稿日時: 2005-01-27 13:54
Http.Post()とやらの関数の仕様をきちんと調査した方が良いかと思い
ます。 Httpクライアント側で使用するAPIライブラリが、Httpリクエスト送信 メソッドを、「リクエスト送信〜レスポンス受信完了まで待機(途中で エラーが発生したら例外送出など)」とするよう実装するのは、通常の ことかと思いますよ。 HttpServletResponseが所有するOutputStreamは、文字通りストリーム ですので、ストリームのバッファサイズを超えるメモリを消費することは 無いですよ。下のレイヤはソケットですので、送信先の受け取り処理が 間に合って無い状態で、送信元でバッファがあふれるほどwriteしようと すれば、writeの呼び出しで、writeを呼び出しているスレッドがブロック するはずです。 [ メッセージ編集済み 編集者: シュン 編集日時 2005-01-27 13:57 ] |
|
投稿日時: 2005-01-27 14:53
シュンさん,ご回答ありがとうございます。
>送信元でバッファがあふれるほどwriteしようとすれば、 >writeの呼び出しで、writeを呼び出しているスレッドがブロックするはずです。 これが知りたかったことです!すっきりしました。 Webブラウザの場合もdoPostを抜けるまで応答がないものと勘違いしておりました (実際はそうでないことを確認しました)。 ただ,ここでWebブラウザ,WebサーバとServletコンテナの間で 何が起こっているのかは残念ながらよく理解していません。 クライアント側HTTPモジュールのPostメソッドが Responseの応答を待つ仕様なのは確認しました。 となると,スレッドを使用してdoPostはすぐに抜けるように実装する方向で サンプルを作ってみようと思っています。 結果が出ましたらポストします。ありがとうございました。 |
|
投稿日時: 2005-01-27 20:57
>スレッドを使用してdoPostはすぐに抜けるように実装する方向で
これも結局のところ私の勘違いでした。 // Delphiコードですみません。 // HTTPは通信を行うオブジェクトです。 // response にファイル出力ストリームを渡したところ, // 一気にファイルに落とす処理を実装できました。 // 余談ですが,Servlet側で DeflaterOutputStream を使用しているため, // クライアントで解凍処理を行う必要があるのですが, // "解凍を行うOutputStream" が存在しないため,自作する必要があり, // かなり悪戦苦闘しました(泣) Http.Post(url, param, response); なんとかサンプルを動作させることができました。 どうもありがとうございました。 |
1
