![Lv.9 ストリーミングで徐々に出力したい [play framework2.0] [java]](https://soylatte.jp/wp-content/themes/soy-magazine/assets/images/no-thumbnail.png)
Content-Lengthを判定する際には、レスポンスのデータをメモリにロードする必要が
あるわけで、ある程度の大きさのデータなら問題ないとして、気になるのは大きいデータの場合、
メモリにロードするって大丈夫なんだろうか。
いや、大丈夫じゃない。
目次
静的なデータの扱い方
playではちゃんとヘルパーを用意してくれているとのことなので、わりかし簡単でした。
よかったー。
[java toolbar=”false”]public static Result index() {
// ファイル名からContent-Typeを勝手に判断してくれる
return ok(new java.io.File(“/tmp/fileToServe.pdf”));
}
[/java]
// ファイル名からContent-Typeを勝手に判断してくれる
return ok(new java.io.File(“/tmp/fileToServe.pdf”));
}
[/java]
上記のコードでは、Content-Dispositionも追記してくれるらしい。
デフォルトではダウンロードするような記述を追記してくれる。
[java toolbar=”false”]Content-Disposition: attachment; filename=fileToServe.pdf.[/java]
こんな感じで。
動的に生成されるデータの扱い方
※理系学生日記さんに解説がありました。感謝。ひよこの絵が激しくかわいい、、、。
動的な場合は、(playに限らず)Chunked transfer encoding※を使わないといけないらしい。
Content-Lengthの代わりに、Transfer-Encodingを使うことになる。
メリット
こうすることで、動的なデータが全て生成される前に、送信可能になったデータから順繰りと
クライアントに返すことができる模様。
デメリット
ただし、どのくらい大きいのか、最終的なデータサイズは生成が終わらないと分からない
ので、プログレスバーや「あと何秒」みたいな表記が適切に表示されないというデメリットもある。
実装方法
方法としては3種類が公式ドキュメントには載ってました。
・InputStream
・String
・byte[]
のいづれかで動的に生成されるデータを扱うらしい。
(Stringの場合)
[java toolbar=”false”]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]
{
// Prepare a chunked text stream
Chunks
{
// Called when the stream is ready
public void onReady(Chunks.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の動画。