如何使用netty通过HTTP流式传输响应

时间:2013-08-19 02:53:05

标签: netty

我正在使用Netty 3.6.6,我想向调用者发送一个大的响应。我无法将响应主体复制到ChannelBuffer中,因为在某些情况下它会非常大。

我正在将服务器从CXF迁移到Netty,以前,我可以使用CXF提供的OutputStream来写入数据。

我最初尝试发送没有内容的响应,然后继续在一系列8k缓冲区中将数据写入Channel。这失败了,因为客户端似乎得到了原始响应并且看不到任何数据和抱怨。我尝试将响应设置为chunked,但这似乎没有什么区别,也没有设置chunked头,客户端总是看到一个空流。

我看到了3.6.6的文件服务器示例,这与我想要做的类似,除了数据不是文件。我看到了ChunkedStream& NioStream,它似乎接近我需要的,除了它们采用InputStream / ReadableByteChannel,而我有一个OutputStream;我可以尝试使用PipedInput& OutputStreams,但这似乎会带来一个不幸的瓶颈。

我确信有一种方法可以将大量数据流回客户端以响应请求,但我只是没有看到如何操作,除非我有一个文件。

我也很好奇如果连接保持活动状态,你是否让客户知道响应是否已完成,你是否正在流式传输内容,但不知道内容长度。似乎客户端会在这些情况下永远等待连接关闭。

修改3.6.6中的静态文件服务器示例以删除内容长度标题(只是将其注释掉),指定它是一个分块响应

   response.setChunked(true);
   response.setHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);

然后在写完回复后使用ChunkedNioStream发送文件:

    // Write the initial line and the header.
    ch.write(response);

    final ReadableByteChannel aIn = java.nio.channels.Channels.newChannel(new FileInputStream(file));
    ChannelFuture writeFuture = ch.write(new ChunkedNioStream(aIn));

产生不良行为,客户端获得几百个字节然后停止接收,基本上就是我在应用程序中看到的内容。正确的事情似乎只发生在内容长度上,这在我的用例中是不可行的。

1 个答案:

答案 0 :(得分:5)

当您尝试将ChunkedNioStream写入ChunkedWriteHandler时,它只会生成一个包含仅ChunkedNioStream 的内容的流。也就是说,它产生ChannelBuffer而不是HttpChunk s。

由于HttpMessageEncoder仅处理HttpMessageHttpChunkChannelBuffer生成的ChunkedNioStream被绕过线路,没有预先添加HTTP块标头,导致您的浏览器困惑。

要解决此问题,您必须实现自己的ChunkedInput生成HttpChunk而非ChannelBuffer s。但是,我必须同意这可能是一项具有挑战性的任务,因此您可能只想分叉HttpMessageEncoder,以便它也理解ChannelBuffer并将其视为HttpChunk。有关详细信息,请查看HttpMessageEncoder的{​​{3}}。