我正在尝试实现一个http服务器(使用netty),它不仅提供“常规”html页面,而且还提供大文件。因此,我想在我的管道中使用ChunkedWriteHandler
和HttpContentCompressor
。
当前,此管道初始化如下:
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("aggregator", new HttpObjectAggregator(1048576));
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
pipeline.addLast("deflater", new HttpContentCompressor());
pipeline.addLast(new NettyHandler());
NettyHandler
遵循此方案:@Override
public void channelRead(final ChannelHandlerContext context, final Object message) throws Exception {
try {
if (message instanceof HttpRequest) {
final HttpRequest request = (HttpRequest) message;
final HttpContext httpContext = new HttpContext(request, context);
final ChannelFuture future = handleHttpMessage(httpContext);
httpContext.closeOn(future);
}
} finally {
ReferenceCountUtil.release(message);
}
}
private ChannelFuture handleHttpMessage(final HttpContext context) {
//writing to the wire via ChannelHandlerContext.write(...)
return context.getChannelContext().writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
}
如果我请求/发送小文件(我的测试文件大约是500字节),一切正常。但一旦请求的文件变大(我的测试文件大约350MB),浏览器(在chrome和firefox中测试)就会报告接收到的正文的编码部分出现问题。chrome说
ERR_CONTENT_DECODING_FAILED
,firefox说类似source file could not be read
。我做错了什么吗?我必须在飞行中操纵管道吗?在此提前感谢您的帮助!
最佳答案
由于httpcontentcompressor无法理解bytebuf实例,因此需要将写入的块包装成defaulthttpcontent。
所以只需在channelpipeline中放置一个特殊的httpcontentcompressor,它知道如何处理bytebuf实例。像这样的:
https://github.com/eclipse/vert.x/blob/compress/vertx-core/src/main/java/org/vertx/java/core/http/impl/HttpChunkContentCompressor.java
一定要把它放在chunkedwritehandler之前。