在Apache HttpClient 4.x中多次读取响应体。

4

我在我的应用程序中使用Apache HttpClient 4.2.3。我们将HTTP调用的响应存储如下:

HttpResponse httpResponse = (DefaultHttpClient)httpClient.execute(httpRequest);

4.x API中响应体是一个InputStream:
InputStream responseStream = httpResponse.getEntity().getContent();

我的问题是,在应用程序的各个点上,我需要将响应正文作为字符串和字节数组读取。但是,Apache使用的InputStream是EofSensorInputStream,这意味着一旦到达流的EOF,它就会关闭。有没有办法多次获取字符串和字节数组表示,并且不关闭流?
我已经尝试过将字节数组包装在新的ByteArrayInputStream中,并将其设置为请求正文,但由于我的响应正文可能达到几千兆字节,因此它不起作用。我还尝试了this,但我注意到原始响应流仍然被关闭。
欢迎任何指针。
编辑:另外,如果我可以在不消耗流或通过反向消耗来找到InputStream的长度,那将非常好。
1个回答

3

1. 我认为你有一些矛盾的要求:

a)

因为我的响应主体可能达到几个G,所以它无法工作

b)

有没有办法多次获取字符串和byte []表示,并不关闭流

如果你没有足够的内存,这是不可能的。

另外,以字节形式获取响应的另一种方法是 EntityUtils.byte[] toByteArray(final HttpEntity entity)

你真的需要N-gigs字符串吗?你要用它做什么?

2.

如果我能找到InputStream的长度就更好了

httpResponse.getEntity().getContentLength()

3. 由于响应不能适应内存,我建议将其保存到文件(或临时文件)中。然后在该文件上设置InputStream,然后根据需要多次读取它。


1
IOUtils或EntityUtils会给你byte[],因为它们会读取整个流,而在这种情况下(EofSensorInputStream),流会被关闭。这意味着我不能再次调用response流上的getAsByteArray(InputStream)。另外,关于内存问题,我可能可以负担得起一次性将大型byte[]加载到内存中,但不能超过这个大小。 - Karthik V
@Karthik.V 一旦你从EntityUtils.toByteArray()获取到byte[],你就会得到你想要的单个数据副本。你也可以将它包装成ByteArrayInputStream,这不应该导致OutOfMemoryError,因为ByteArrayInputStream不会复制byte[]。顺便说一下,你不应该长时间保留响应,记住这是来自远程服务器的响应。你打算如何重新读取它?那会导致服务器再次发送N-gigs给你吗?请参见我的答案中关于如何多次重新读取大型响应的第3项。 - Vitaly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接