【问题标题】:Android GZIP decompression result is cut offAndroid GZIP解压结果被截断
【发布时间】:2011-11-19 23:14:08
【问题描述】:

我从我们的服务器收到一个 JSON 响应,它是使用 gzip 压缩的。我尝试了许多解码数据并吐出结果的方法,但是所有这些方法都导致数据被缩短。我没有得到完整的 JSON 响应。

我根据谷歌示例使用了以下内容,并且相信它应该可以工作。我还有什么遗漏吗?

API.client.addResponseInterceptor(new HttpResponseInterceptor() {
         public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException {
            HttpEntity entity = response.getEntity();
            Header contentEncodingHeader = entity.getContentEncoding();
            if (contentEncodingHeader != null) {
               HeaderElement[] codecs = contentEncodingHeader.getElements();
               for (int i = 0; i < codecs.length; i++) {
                  if (codecs[i].getName().equalsIgnoreCase(API.GZIP)) {
                     response.setEntity(new GzipDecompressingEntity(response.getEntity()));
                     return;
                  }
               }
            }
         }
      });


static class GzipDecompressingEntity extends HttpEntityWrapper {
          public GzipDecompressingEntity(final HttpEntity entity) {
             super(entity);
          }

          @Override
          public InputStream getContent() throws IOException, IllegalStateException {
             // the wrapped entity's getContent() decides about repeatability
             InputStream wrappedin = wrappedEntity.getContent();
             return new GZIPInputStream(wrappedin);
          }

          @Override
          public long getContentLength() {
             // length of ungzipped content is not known
             return -1;
          }
}

我得到他的响应和使用下面的字符串返回。

response = API.client.execute(postMethod);
        Log.i(LOG_TAG_GENERAL, "STATUS CODE: " + String.valueOf(response.getStatusLine().getStatusCode()));

        BasicResponseHandler handler = new BasicResponseHandler();
        resp = handler.handleResponse(response);

任何帮助将不胜感激

【问题讨论】:

  • 您可以尝试切换到HttpURLConnection。它提供透明的 GZip 编码。这也是在 Android 上执行 HTTP 操作的新 Google 推荐。
  • 我重写了使用 HttpURLConnection 的方法,但是我仍然遇到同样的问题。服务器正在使用 https 但是身份验证并且所有似乎都在工作,因为我正在检索 JSON 响应(只是不是全部)。同样通过阅读文档,似乎 HttpURLConnection 应该透明地创建一个 HttpsURLConnection 对象。

标签: android gzip httpclient


【解决方案1】:

您需要致电entity.consumeContent() 以确保一切都得到处理。最好调用带有处理程序参数的执行方法,它会做正确的事情。像这样的:

String responseStr = httpclient.execute(get, responseHandler);

作为记录,HttpURLConnection API 很烂。

【讨论】:

  • 所以在 postmethod 中我添加了 getEntity().consumeContent() 并且我直接在 execute 方法中添加了一个 响应处理程序。然后我打印出响应,响应字符串仍然被切断。还有其他想法吗?
【解决方案2】:

好的,谢谢 Mark Murphy(不确定是不是你)和 Nikolay。我使用了您的两个建议,但仍然收到相同的错误。但是正因为如此,我更关注结果的实际内容。基本上返回的结果太大而不能简单地吐到我认为可能是这种情况的日志中,但生成的 JSONArray 的长度也更短,但这是由于服务器端的变化,因此我的思想太狭隘了一个初级错误。

我对 HttpURLConnection 为何“糟糕”很感兴趣。我的意思是在视觉上打开与输入和输出流等的连接非常难看。我坚持只使用 ResponseInterceptor 但是我的 HttpURLConnection 代码将保持注释掉并且不会被删除,直到我确定它“糟透了”。

【讨论】:

  • 我说 API 很烂。它只是一个有一百个 getter/setter 方法的类,你必须使用(并记住)魔法属性来改变行为,整个 doInput/Output() 事情很丑陋。也就是说,实际的代码可能会快速、高效等。我只是觉得 API 丑陋且难以使用。
  • @NikolayElenkov:作为一个 API,它很烂。然而,这就是为什么谷歌可以在不破坏其糟糕的 API 的情况下为其添加新功能的原因。由于逻辑分布在许多类中,因此他们几乎无法轻松地对 HttpClient 执行此操作。这就是为什么HttpURLConnection 是新的官方推荐。至少,一些 Google 员工是这么告诉我的。
  • 我也听说过。许多具有有意义的名称和职责的类总是更好。通过添加类来添加新功能比通过向单个类添加更多方法和魔术参数来添加功能要好。如果他们必须做更多的工作来实现这一目标,他们应该:)。
  • 好吧,因为我希望我的代码快速、高效且经得起时间考验,所以我将使用 HttpURLConnection。我同意拥有两个流并单独处理每个流的超级丑陋。对我来说,它感觉非常实用 vs 面向对象。我也喜欢 HttpURLConnection 如何自动处理 gzip。如果在未来的版本中做出任何更快的改进,它们很可能是透明的,从而节省了我重写 ResponseInterceptor 等的时间。这就是我证明我的决定的理由。再次感谢所有帮助。
  • HttpURLConnection 确实很糟糕。如果您没有设置读取/连接超时并且远程服务器挂起(例如,来自 Thread.sleep)并且您自己的互联网连接短暂断开,您可能有一个不会完成的线程,直到您重启你的机器。如果与远程服务器的连接由于高负载而挂起,并且您得到 SocketException: end of file达到,则同样的情况。如果您在那之后在连接上尝试 getInputStream() ,它将永远挂起。 IMO 这对于企业软件来说是非常不可接受的。 HttpURLConnection 糟透了!使用 apache 的 HTTP 客户端
猜你喜欢
  • 2014-05-07
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
  • 2010-11-03
  • 2019-12-19
  • 2014-10-21
  • 2012-06-26
  • 1970-01-01
相关资源
最近更新 更多