Sharable

システム&ウェブのシェアラブル

Lv.9 ストリーミングで徐々に出力したい [play framework2.0] [java]

2012年3月29日

Content-Lengthを判定する際には、レスポンスのデータをメモリにロードする必要が
あるわけで、ある程度の大きさのデータなら問題ないとして、気になるのは大きいデータの場合、
メモリにロードするって大丈夫なんだろうか。
いや、大丈夫じゃない。

目次

静的なデータの扱い方

playではちゃんとヘルパーを用意してくれているとのことなので、わりかし簡単でした。
よかったー。

public static Result index() {
  // ファイル名からContent-Typeを勝手に判断してくれる
  return ok(new java.io.File("/tmp/fileToServe.pdf"));
}

上記のコードでは、Content-Dispositionも追記してくれるらしい。
デフォルトではダウンロードするような記述を追記してくれる。

Content-Disposition: attachment; filename=fileToServe.pdf.

こんな感じで。

動的に生成されるデータの扱い方

理系学生日記さんに解説がありました。感謝。ひよこの絵が激しくかわいい、、、。

動的な場合は、(playに限らず)Chunked transfer encoding※を使わないといけないらしい。
Content-Lengthの代わりに、Transfer-Encodingを使うことになる。

メリット

こうすることで、動的なデータが全て生成される前に、送信可能になったデータから順繰りと
クライアントに返すことができる模様。

デメリット

ただし、どのくらい大きいのか、最終的なデータサイズは生成が終わらないと分からない
ので、プログレスバーや「あと何秒」みたいな表記が適切に表示されないというデメリットもある。

実装方法

方法としては3種類が公式ドキュメントには載ってました。
・InputStream
・String
・byte[]
のいづれかで動的に生成されるデータを扱うらしい。

(Stringの場合)


public static Result index()
{
// Prepare a chunked text stream
Chunks chunks = new StringChunks()
{
// Called when the stream is ready
public void onReady(Chunks.Out out)
{
for (int i = 0; i < 1000; i++) { out.write("あ"); out.write("い"); out.write("う"); out.write("え"); out.write("お!"); } out.close(); } }; return ok(chunks); } [/java]

一応動いた。

※onReadyメソッドは、ストリームが送信可能になったタイミングで実行されるっぽい。

たしかに通常の出力方法に比べて、徐々に出力されていたので、ちゃんと動いたんだと思う!
・今回のplay framework2.0の動画。

このエントリーをはてなブックマークに追加