【问题标题】:Getting UnknownLengthHttpInputStream while getting InputStream from HttpURLConnection in android在android中从HttpURLConnection获取InputStream时获取UnknownLengthHttpInputStream
【发布时间】:2023-04-06 20:22:01
【问题描述】:

HttpURLConnection.getInputStream() 给出 UnknownLengthHttpInputStream 并且由于此 Document 解析引发 SAX 解析器异常。

以下是代码

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 Project 中完美运行。

以下是 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)

提前致谢。

【问题讨论】:

  • 附加来自 logcat 的异常?
  • @Jens 我附上了来自 logcat 的异常..
  • 您获得了UnknownLengthHttpInputStream 流,因为您的服务器没有提供Content-Length 或使用分块传输编码。当服务器不提供任何一个时,它必须通过关闭连接来发出 HTTP 正文的结束信号——在这种情况下,它似乎在中间文档中执行。执行此调用时是否有可能嗅探 Web 服务器流量(例如使用 WireShark)?
  • 尝试在赋值后立即打印“xml”变量。它是在控制台上打印响应还是生成错误?
  • 对于 SOAP 调用尝试使用 KSoap2 而不是 HTTP 调用

标签: java android web-services inputstream saxparser


【解决方案1】:

它可能是 Http 1.0(旧服务器或配置错误)服务器或未配置保持活动状态。在这种情况下,流的长度在从服务器关闭连接时是已知的。尝试在您的请求标头中指定 http1.1 和 keep-alive(一些谷歌搜索会有所帮助)。只有在服务器响应中指定了内容长度属性,你才会提前知道流的长度。

解决方法: 将http流完全读入ByteBufferStream(直到read()返回-1)。然后将 ByteBufferInputStream 扔到你的库中(现在知道长度)

【讨论】:

    【解决方案2】:

    您是否尝试过为此使用 apache 库?我建议如下:

    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 本身的流。 喜欢:

    InputStream st = entity.getContent();
    

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

    【讨论】:

      【解决方案3】:

      要处理响应,请使用此方法,它将处理所有问题!

      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();
         }
      

      【讨论】:

        【解决方案4】:

        曾经这样尝试过

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

        【讨论】:

          【解决方案5】:

          SAX 解析器 无法获得InputStream 数据的长度时,问题就来了。要解决这个问题,将从xml (InputStream) 读取的内容保存到一个String 变量中,并从parseDocumentBuilder 方法的变量中创建一个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 构建的。

          【讨论】:

            【解决方案6】:

            您需要在服务中正确关闭输出流以避免此异常。 如果您使用的是第三方库,请确保您已设置响应标头

            Content-Type
            Content-Length
            

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

            File.length()
            

            【讨论】:

            • HTTP 协议说,在特定情况下,您可以得到没有 Content-Length 标头的响应:w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 此外,您不能总是修改您调用的服务,因为它并不总是您的。
            • 你有什么建议的解决方案?
            • 老实说,我认为这是因为修复了请求类型。 by connection.setRequestProperty("Accept", "application/xml"); 你可能不知道 URL 是如何响应的。
            猜你喜欢
            • 2011-07-19
            • 1970-01-01
            • 2013-08-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-07-24
            • 1970-01-01
            相关资源
            最近更新 更多