在Android中从HttpURLConnection获取InputStream时获取UnknownLengthHttpInputStream

HttpURLConnection.getInputStream()给出UnknownLengthHttpInputStream,并由于这个文档parsing抛出SAXparsing器exception。

以下是代码

try{ URL url = new URL(uri); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "application/xml"); InputStream xml = connection.getInputStream(); System.out.println(connection.getResponseCode()); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(connection.getInputStream()); doc.getDocumentElement().normalize(); }catch(Exception e){ e.printStackTrace(); } 

任何人都知道UnknownLengthHttpInputStream的原因。 我得到这个错误只在android和这个代码完美的Java项目。

以下是来自LogCat的例外:

 08-08 11:07:40.490: W/System.err(1493): org.xml.sax.SAXParseException: Unexpected end of document 08-08 11:07:40.504: W/System.err(1493): at org.apache.harmony.xml.parsers.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:129) 08-08 11:07:40.510: W/System.err(1493): at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:107) 08-08 11:07:40.510: W/System.err(1493): at com.example.testws.MainActivity.onCreate(MainActivity.java:59) 08-08 11:07:40.520: W/System.err(1493): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611) 08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663) 08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.access$1500(ActivityThread.java:117) 08-08 11:07:40.530: W/System.err(1493): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) 

提前致谢。

Solutions Collecting From Web of "在Android中从HttpURLConnection获取InputStream时获取UnknownLengthHttpInputStream"

它可能是一个Http 1.0(旧服务器或错误configuration)服务器或没有保持活着configuration。 在这种情况下,在从服务器closures连接时,stream的长度是已知的。 尝试指定http1.1并保持在您的请求标头(一些谷歌search将有助于这一点)。 只有在服务器响应中指定了内容长度属性时,才会提前知道stream的长度。

解决方法:将httpstream完全read()ByteBufferStream (直到read()返回-1 )。 然后把ByteBufferInputStream放到你的库中(长度现在是已知的)

你有没有尝试过使用这个Apache库? 我会build议如下:

 try { HttpClient client = new DefaultHttpClient(); String getURL = "http://www.google.com"; HttpGet get = new HttpGet(getURL); HttpResponse responseGet = client.execute(get); HttpEntity resEntityGet = responseGet.getEntity(); if (resEntityGet != null) { //do something with the response Log.i("GET RESPONSE",EntityUtils.toString(resEntityGet)); } } catch (Exception e) { e.printStackTrace(); } 

然后获取HttpEntity本身的stream。 如下所示:

 InputStream st = entity.getContent(); 

更多示例: http : //www.softwarepassion.com/android-series-get-post-and-multipart-post-requests/

处理响应使用这种方法,它会照顾所有的!

 public static ResponseHandler<String> getResponseHandlerInstance(final Handler handler) { final ResponseHandler<String> responseHandler = new ResponseHandler<String>() { public String handleResponse(final HttpResponse response) { Message message = handler.obtainMessage(); Bundle bundle = new Bundle(); StatusLine status = response.getStatusLine(); Log.d(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " statusCode - " + status.getStatusCode()); Log.d(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " statusReasonPhrase - " + status.getReasonPhrase()); HttpEntity entity = response.getEntity(); String result = null; if (entity != null) { try { result = HTTPRequestHelper.inputStreamToString(entity.getContent()); bundle.putString("RESPONSE", result); message.setData(bundle); handler.sendMessage(message); } catch (IOException e) { Log.e(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG, e); bundle.putString("RESPONSE", "Error - " + e.getMessage()); message.setData(bundle); handler.sendMessage(message); } } else { Log.w(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " empty response entity, HTTP error occurred"); bundle.putString("RESPONSE", "Error - " + response.getStatusLine().getReasonPhrase()); message.setData(bundle); handler.sendMessage(message); } return result; } }; return responseHandler; } private static String inputStreamToString(final InputStream stream) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(stream)); StringBuilder sb = new StringBuilder(); String line = null; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } br.close(); return sb.toString(); } 

一旦尝试像这样

 if(connection.getResponseCode() ==HttpURLConnection.HTTP_OK){ InputStream xml = connection.getInputStream(); .......... }else{ //problem in URI/connection ..... } 

这里的问题出现在SAXparsing器无法获得InputStream数据的长度时。 要解决此问题,请将从xmlInputStream )中读取的内容保存到一个Stringvariables中,并从DocumentBuilder parse方法的variables中创build一个InputStream 。 要做到这一点修改你的代码如下:

 try { URL url = new URL(uri); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Accept", "application/xml"); InputStream xml = connection.getInputStream(); DataInputStream dis = new DataInputStream(xml); StringBuilder sb = new StringBuilder(); int asci = dis.read(); while (asci > 0) { sb.append((char) asci); asci = dis.read(); } String inputXML = sb.toString(); String predefinedXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <EmotionDB></EmotionDB>"; InputStream inputStream = new ByteArrayInputStream(inputXML.getBytes());//use predefinedXML.getBytes() instead of inputXML.getBytes() for sample test System.out.println(connection.getResponseCode()); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(inputStream); doc.getDocumentElement().normalize(); } catch (Exception e) { e.printStackTrace(); } 

这里的inputStream将有一个正确的内容长度,因为它是由ByteArrayInputStream和固定的字节数构成的。

您需要在服务中正确closures输出stream以避免此exception。 如果您正在使用第三方库,请确保已经设置了响应标头

 Content-Type Content-Length 

如果您使用的是Java服务,则可以从方法获取内容长度

 File.length()