当总数据大小未知时,我试图围绕 Netty 4 实现 HTTP 服务器的方式来使用分块传输编码服务 HttpResponses 主体。
作为一个起点,我只是更改了 HttpStaticFileServerHandler(在https://github.com/netty/netty/tree/netty-4.0.0.CR1/example/src/main/java/io/netty/example/http中找到/file)使用 ChunkedStream 而不是 ChunkedFile(它们都是 ChunkedByteInputs)。
我知道在原始示例用例中使用 FileInputStream 并不理想,但我认为它是重用已知代码的一个很好的示例。
因此,这里是与 io.netty.example.http.file 包中的 HttpStaticFileServerHandler 类的差异(与 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
变化很小:使用 FileInputStream 代替 RandomAccessFile 和 ChunkedStream 代替 ChunkedFile。管道未受影响。
要重现,只需将更改应用到 Netty 示例,运行它并尝试下载任何文件。
在此更改之后,目录列表显然有效,因为响应没有分块,但文件下载却没有。客户端下载文件但从未完成下载,保持连接并永远等待。我已经尝试了从浏览器到 curl、wget 等的几种方法。我还尝试将 ByteLoggingHandler 添加到管道中,我可以看到一个空的尾随块,所以我不明白为什么浏览器仍在等待数据。
有什么线索吗?