合計データサイズが不明な場合に、チャンク転送エンコーディングを使用して HttpResponses ボディを提供する HTTP サーバーを実装する Netty 4 の方法に頭を悩ませようとしています。
出発点として、単純に HttpStaticFileServerHandler を変更しました ( https://github.com/netty/netty/tree/netty-4.0.0.CR1/example/src/main/java/io/netty/example/httpにあります)。 /file ) ChunkedFile の代わりに ChunkedStream を使用します (どちらも ChunkedByteInputs です)。
FileInputStream を使用することは、元のサンプル ユース ケースでは理想的ではないことを理解していますが、既知のコードを再利用する良い例になると思います。
したがって、ここに io.netty.example.http.file パッケージの HttpStaticFileServerHandler クラスに対する差分があります (vs. 4.0.0.CR1):
diff --git a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java
index 904579b..0d3592f 100644
--- a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java
+++ b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java
@@ -27,13 +27,14 @@ import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
-import io.netty.handler.stream.ChunkedFile;
+import io.netty.handler.stream.ChunkedStream;
import io.netty.util.CharsetUtil;
import javax.activation.MimetypesFileTypeMap;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.RandomAccessFile;
+import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
@@ -159,17 +160,15 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda
}
}
- RandomAccessFile raf;
+ InputStream raf; // Use an InputStream instead of a RandomAccessFile
try {
- raf = new RandomAccessFile(file, "r");
+ raf = new FileInputStream(file);
} catch (FileNotFoundException fnfe) {
sendError(ctx, NOT_FOUND);
return;
}
- long fileLength = raf.length();
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
- setContentLength(response, fileLength);
setContentTypeHeader(response, file);
setDateAndCacheHeaders(response, file);
if (isKeepAlive(request)) {
@@ -180,7 +179,7 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda
ctx.write(response);
// Write the content.
- ChannelFuture writeFuture = ctx.write(new ChunkedFile(raf, 0, fileLength, 8192));
+ ChannelFuture writeFuture = ctx.write(new ChunkedStream(raf)); // Use a ChunkedStream instead of a ChunkedFile
// Decide whether to close the connection or not.
if (!isKeepAlive(request)) {
そして、ここで完全に変更されたファイル: https://gist.github.com/eskatos/5311587
変更は最小限です。RandomAccessFile の代わりに FileInputStream を使用し、ChunkedFile の代わりに ChunkedStream を使用します。パイプラインはそのままです。
再現するには、変更を Netty の例に適用し、実行して、任意のファイルをダウンロードしてみてください。
この変更の後、応答はチャンク化されませんが、ファイルのダウンロードはチャンク化されないため、ディレクトリ リストは明らかに機能します。クライアントはファイルをダウンロードしますが、ダウンロードを終了せず、接続を保持して永遠に待ちます。ブラウザーからcurl、wgetなどまでいくつか試しました。また、ByteLoggingHandlerをパイプラインに追加しようとしましたが、空の末尾のチャンクが表示されるため、ブラウザーがまだデータを待機している理由がわかりません。
どんな手掛かり?