Android:HTTP通信应使用“ Accept-Encoding:gzip”


109

我与网络服务器进行HTTP通信,请求JSON数据。我想使用压缩此数据流Content-Encoding: gzip。我可以Accept-Encoding: gzip在HttpClient中进行设置吗?gzip正如您在此处看到的那样,Android参考中的搜索未显示与HTTP相关的任何内容。


1
Android-WebRequest自动支持GZIP和未压缩的响应,例如通过new WebRequest().get().to("http://www.example.com/").askForGzip(true).executeSync()。具体来说,方法parseResponse(...)应该是您要寻找的。
caw

Answers:


174

您应该使用http标头来指示连接可以接受gzip编码的数据,例如:

HttpUriRequest request = new HttpGet(url);
request.addHeader("Accept-Encoding", "gzip");
// ...
httpClient.execute(request);

检查响应以进行内容编码:

InputStream instream = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
    instream = new GZIPInputStream(instream);
}

7
对于我需要的所有细节,这是一个很好的帮助,非常有用。非常感谢。一个评论:我使用setHeader代替addHeader。据我了解,如果有的话,这将覆盖现有的“接受编码”。不知道哪种方法是正确/更好的方法。覆盖现有标头以确保其具有正确的值,或在可以并行存在其他Accept-Encoding标头的情况下添加它。
znq

那你放在哪里?
Mikey 2010年

7
这不会gzip请求,它只会告诉服务器您可以接受gzip的响应。
Jeffrey Blattman

1
对于任何人也有麻烦得到这个启动和运行谷歌服务在这里是它花了我不少时间去找出两个问题:(1)一些谷歌的服务,需要由客户端提供的用户代理字符串包含字符串gzip,以真正实现gzip压缩。(2)请记住,如果服务器的响应太小,则可能无法gzip响应...
sven 2011年

我的问题是gzip标头无处可见。我正在使用Wireshark嗅探服务器端的网络,但看不到我在android中添加的“ gzip”标头的踪迹...
Ted

33

如果您使用的是API级别8或更高版本,则有AndroidHttpClient

它具有以下辅助方法:

public static InputStream getUngzippedContent (HttpEntity entity)

public static void modifyRequestToAcceptGzipResponse (HttpRequest request)

导致更简洁的代码:

AndroidHttpClient.modifyRequestToAcceptGzipResponse( request );
HttpResponse response = client.execute( request );
InputStream inputStream = AndroidHttpClient.getUngzippedContent( response.getEntity() );

很好的提示ModifyRequest&getUngzipped,同样,我需要复制EntityUtils.toString(HttpEntity)来将未压缩的流解析为String
Marcos Vasconcelos

1
AndroidHttpClient被弃用API级别22
亚历克斯Kucherenko

13

我认为此链接上的代码示例更有趣: ClientGZipContentCompression.java

他们正在使用HttpRequestInterceptorHttpResponseInterceptor

索取样品:

        httpclient.addRequestInterceptor(new HttpRequestInterceptor() {

            public void process(
                    final HttpRequest request,
                    final HttpContext context) throws HttpException, IOException {
                if (!request.containsHeader("Accept-Encoding")) {
                    request.addHeader("Accept-Encoding", "gzip");
                }
            }

        });

答案样本:

        httpclient.addResponseInterceptor(new HttpResponseInterceptor() {

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

        });

1
您为何认为它更有趣?
Gaurav Agarwal

3
@codingcrow您正在寻找的是:在这种特殊情况下,通过添加两个协议拦截
clauziere 2012年


在android.jar(2.2)中
找不到GzipDecompressingEntity

1

我没有使用过的GZip,但我认为你应该从你使用的输入流HttpURLConnectionHttpResponse作为GZIPInputStream,而不是某些特定的其他类。


HTTPURLConnection默认情况下已启用gzip。您只需要确保您的Web服务器可以返回gzip页面即可。 developer.android.com/reference/java/net/HttpURLConnection.html 我可以使用ob_start(“ ob_gzhandler”)从php返回gzip页面。
metric152

没有答案时不要回答!
Martin.Martinsson

0

就我而言,是这样的:

URLConnection conn = ...;
InputStream instream = conn.getInputStream();
String encodingHeader = conn.getHeaderField("Content-Encoding");
if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip"))
{
    instream = new GZIPInputStream(instream);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.