2013-08-19 79 views
2

我正在使用Netty 3.6.6,我想发送一个大的响应给调用者。我无法将响应正文复制到ChannelBuffer中,因为在某些情况下它会非常大。如何通过HTTP流式传输一个响应netty

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

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

我看到3.6.6的文件服务器示例,这与我想要做的类似,只是数据不会是文件。我看到NioStream的ChunkedStream &,它似乎接近我所需要的,除了它们采用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)); 

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

回答

5

当您尝试写一个ChunkedNioStreamChunkedWriteHandler,它仅生成包含的ChunkedNioStream的内容流。也就是说,它产生了ChannelBuffers而不是HttpChunks。

因为HttpMessageEncoder仅处理HttpMessageHttpChunk,通过ChunkedNioStream产生ChannelBuffer旁通到导线,没有前置HTTP块头部,导致浏览器混淆。

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

+0

这似乎是固定在Netty 4.x'ChunkedInput',对吧? –