标签:java httpclient apache-httpclient-4-x apache-commons-httpclient
有一个api我需要执行没有长度的八位字节流.它只是一个实时数据流.我遇到的问题是,当我提出请求时,它似乎试图在将信息读入输入流之前等待内容的结束,但是它没有看到内容的结束和超时与NoHttpResponse异常.以下是我的代码的简化版本:
private static HttpPost getPostRequest() {
// Build uri
URI uri = new URIBuilder()
.setScheme("https")
.setHost(entity.getStreamUrl())
.setPath("/")
.build();
// Create http http
HttpPost httpPost = new HttpPost(uri);
String nvpsStr = "";
Object myArray[] = nvps.toArray();
for(int i = 0; i < myArray.length; i ++) {
nvpsStr += myArray[i].toString();
if(i < myArray.length - 1) {
nvpsStr += "&";
}
}
// Build http payload
String request = nvpsStr + scv + streamRequest + "\n\n";
// Attach http data
httpPost.setEntity(new StringEntity(URLEncoder.encode(request,"UTF-8")));
return httpPost;
}
// Where client is simply
// private static final CloseableHttpClient client = HttpClients.createDefault();
private static runPostRequest (HttpPost request) {
CloseableHttpResponse response = client.execute(request);
try {
HttpEntity ent = response.getEntity();
InputStream is = ent.getContent();
DataInputStream dis = new DataInputStream(is);
// Only stream the first 200 bytes
for(int i = 0; i < 200; i++) {
System.out.println(( (char)dis.readByte()));
}
} finally {
response.close();
}
}
解决方法:
编辑2
所以,如果你不熟悉线程/ runnables / Handlers并且不熟悉android AsyncTask,我会直接去HttpUrlConnection(用apacheHttpClient删除整个练习因为,基本上googl说HttpUrlConn会支持stream’d响应,它确实有效!)
它可能不像转储标题那样容易检测所有细节.但是,使用正常的流式响应对象,我认为它应该正常工作….请参阅编辑3以获取UrlConn代码示例
EndEdit2
从问题是什么’流’协议被使用(渐进式dwnld | http流)或者如何实际管理客户端上的流式响应不清楚.
建议从连接转储标头,以确切了解客户端和服务器同意的内容?
假设您关闭了UI线程(在asyncTask中或在Handler的回调部分中),因此您可能需要重构一点.
假设http流与apache客户端4.3.5一起使用
如果响应的头部没有长度,那么你在Http 1.1上做了一个’chunked’响应,你必须读取一个缓冲区直到你得到一个’last-chunk’或者决定关闭流或者Connection :
服务器刚刚开始发送(流),客户端应该根据生成实体内容的详细apache说明,通过使用缓冲区来处理它从http响应中获得的’input-stream’.
如果30秒的套接字超时会抢占活动流,我不记得副手吗?请记住,在apache中,构建器中存在用于套接字超时和READ超时的单独设置.不希望套接字关闭,并且不希望在服务器提供响应时等待可读流的可用字节超时.
无论如何,客户端处理程序只需要通过检查读入缓冲区的内容来了解流的结束方式……
如果适当的协议是“继续”& “chunked”然后客户端上的响应处理程序应该在流处理程序循环中UNTIL它从http spec看到LAST-CHUNK.
response.getEntity().getContent()
应该为您提供处理响应流所需的参考,直到’last-chunk’…
我想你应该read here如何消耗一个缓冲的实体,在这个实体中需要多个读取才能在响应中的’last-chunk’结束. HttpUrlConn可能更容易的另一个原因……
做一个处理缓冲读取的循环,直到由匹配’last-chunk’的字节表示的END.
然后根据消费实体和可重用连接的详细apache说明CLO流或CONN.
在apache HttpClient中编辑流响应的代码
在’处理程序的回调或asyncTask中
request.execute();
...
processStreamingEntity(response.getEntity());
response.close();
//implement your own wrapper as mentioned in apache docs
private void processStreamingEntity(HttpEntity entity) throws IOException {
InputStreamHttpEntityHC4 bufHttpEntity = new InputStreamHttpEntityHC4(entity);
while not bufHttpEntity.LAST_CHUNK {
handleResponse(bufHttpEntity.readLine())
}
编辑3
httpUrlConnection版本,如果你去那样. (使用MessageHandler,但你可以使用这些字节,因为这是来自流式语音示例,文本中的单词将被发送回UI)
private void openHttpsConnection(String urlStr, Handler mhandler) throws IOException {
HttpsURLConnection httpConn = null;
String line = null;
try {
URL url = new URL(urlStr);
URLConnection urlConn = url.openConnection();
if (!(urlConn instanceof HttpsURLConnection)) {
throw new IOException ("URL is not an Https URL");
}
httpConn = (HttpsURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.setReadTimeout(50 * 1000);
BufferedReader is =
new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
while ((line = is.readLine( )) != null) {
Message msg = Message.obtain();
msg.what=1;
msg.obj=line;
mhandler.sendMessage(msg);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch( SocketTimeoutException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what=2;
BufferedInputStream in = new BufferedInputStream(httpConn.getErrorStream());
line =new String(readStream(in));
msg.obj=line;
mhandler.sendMessage(msg);
}
finally {httpConn.disconnect();}
}
标签:java,httpclient,apache-httpclient-4-x,apache-commons-httpclient 来源: https://codeday.me/bug/20190930/1837218.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。