当使用HttpClient.execute()发送大请求时,我如何知道它何时完成获取所有内容?

4

我正在处理一个Android相关的问题,但它并不是特定于Android的问题。

使用org.apache.http.client.HttpClient,我可以向一个大小为1kb的URL发出请求,并且整个响应都包含在HttpResponse中:

HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://10.16.83.67/1kb.log");
HttpResponse response = null;
BufferedReader rd = null;

response = client.execute(request);

我可以从响应中获取 HttpEntity:
HttpEntity entity = response.getEntity();
rd = new BufferedReader(new InputStreamReader(entity.getContent()));

然后,使用BufferedReader...

while ((line = rd.readLine()) != null) {
 // ... parse or whatever
}

我正在观察 WireShark,对于上述代码,我看到每个方向都有一次传输:请求日志文件,然后整个日志作为响应被传送。但是,如果我请求更大的内容,比如我的 1MB 日志文件,我会看到非常不同的情况。数据被分成帧并在 rd.readLine() 循环中通过网络流式传输。似乎最初的响应中包含了大约 1kb 的数据。然后,随着 readLine() 的运行,它会向服务器发出其他请求,并将数据流式传输到套接字。如果网络连接中断,我会收到一个 IO 错误。对于大型请求,entity.isStreaming() 是 true。这是一个异步调用(在 Android 上是强制性的,因为不能在 UI 线程上进行网络调用),但我不想继续,直到我确定已经从此请求接收到所有数据。简单地等待一段时间然后继续并希望一切顺利,不幸的是,这不是一个选项。我的问题是:我的 HttpClient、HttpGet、HttpResponse 或 HttpEntity 对象是否知道何时完成从此请求接收数据?还是我必须依赖 BufferedReader 来知道流何时关闭?

如果是流式传输,那就是重点,不需要等待接收完整个数据。此外,我不明白为什么你不想在接收完所有内容之前开始阅读? - njzk2
我并不需要等待它完成后才开始读取工作。我只是想要100%确定它何时完成,最好是通过观察我上面提到的其中一个对象来实现。 - AWT
2个回答

2

您是否正在使用AsyncTask?否则,您可以选择这个

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
 protected Long doInBackground(URL... urls) {}

// 在上面的方法中执行所有的http请求

 protected void onProgressUpdate(Integer... progress) {
     setProgressPercent(progress[0]);
 }

 protected void onPostExecute(Long result) {
     showDialog("I pop up when all the code in the DoInbackground is finished");
 }

}


我喜欢这个想法。如果我只将execute()放在AsyncTask中,它将无法工作。但是,如果我将所有流读取移动到doInBackground()方法中,并在完成读取流后结束,似乎它会做我需要的事情。让我试试。 - AWT

1
你使用的是哪个httpclient?你可能想要对其进行评估。
有一些好的httpclient库,可以使用类似于this的东西。
请注意这个来自3X的例子。我使用4X,没有任何分块响应代码需要发布。
如果你想寻找新的选项,你可以在这里查看。

我正在使用3.1版本... 我会看一下分块代码。它很有趣,但我不确定它是否符合我的需求。感谢提供链接。 - AWT

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