Apache Commons HttpClient支持GZIP压缩吗?

35

Apache Commons HttpClient库支持Gzip吗?我们希望在Apache服务器上启用gzip压缩以加快客户端/服务器通信速度(我们有一个PHP页面,允许我们的Android应用程序与服务器同步文件)。

8个回答

30

Apache HttpClient 4.1默认支持内容压缩以及许多以前被认为超出范围的其他功能。


65
怎样将它从盒子里取出来? - djechlin
1
在4.5.3中,只需使用HttpClientBuilder.create().build()创建客户端,它将为您处理所有gzip请求和响应的解压缩。 - Clement.Xu

19
如果您的服务器可以提供GZIP压缩的内容,在使用Apache Http client 4.1时,您只需要使用下面这行代码:
org.apache.http.impl.client.ContentEncodingHttpClient

这是DefaultHttpClient的一个子类。

该客户端还会添加头信息,表示它接受GZIP压缩的内容。


13
在 HttpClient 4.2.1 版本中,ContentEncodingHttpClient已被弃用;建议用户使用DecompressingHttpClient,详见http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/DecompressingHttpClient.html。 - Hbf
2
@Hbf也被弃用了。 - djechlin
7
从4.3版本开始,应该使用HttpClientBuilder(而不是ContentEncodingHttpClientDecompressingHttpClient)。 - Jonik
2
使用 HttpClientBuilder,你需要在构建器上调用特定的方法来启用gzip吗?还是只需要不调用 disableContentCompression() 方法就可以了? - benkc
1
不,压缩已自动启用。我尝试了4.5.3版本,并使用Wireshark捕获请求和响应:请求中自动添加了“Accept-Encoding: gzip,deflate”标头,响应内容可以自动解压缩。 - Clement.Xu

10
自从4.1版本以来,Apache HttpClients处理请求和响应压缩。
- 无需压缩请求,在请求标头中设置任何“Accept-Encoding”都不需要。 - 它还自动处理响应解压缩,无需处理响应的解压缩。 - 到4.3版本为止,它处理gzip和deflate。你可以在这里查看ResponseContentEncoding api文档:这里
只需使用:
HttpClients.custom()

使用以下内容:

HttpClientBuilder.create()

如果您想在图书馆检查,请前往HttpClientBuilder,它使用RequestAcceptEncodingResponseContentEncoding

您可以通过"disableContentCompression()"来禁用它。

HttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                .disableContentCompression() //this disables compression
                .build();

请确保您添加的任何拦截器都可以覆盖它,谨慎使用。

HttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                .setHttpProcessor(httpprocessor) //this interceptor can override your compression.
                .build();

8
它本身不支持此功能,而且似乎不太可能被添加到HttpClient 3.x中(请参见相当刻薄的JIRA问题在这里)。但是,您可以通过添加自定义请求读取器和手动请求/响应流处理来完成此操作,这些功能建立在基本库之上,但有点麻烦。
看起来您可以使用HttpClient 4来完成此操作,但需要一些努力。
如果你问我,这真的很糟糕,这些东西应该比现在更容易。

2
@karim79: 我已经放弃了任何希望,认为HttpClient被任何掌握实际情况的人维护(就好像HttpClient 4 API没有足够的证据一样)。 - skaffman

1

对于那些(像我一样)由于其他原因无法升级到Apache 4.x.x,并且需要使用他们的Apache的人(顺便说一句,下面的内容首先是针对版本4.3.6实施的,其中显然不支持“开箱即用”,尽管这可能是因为我们总是使用具有其他特定要求的自定义httpclient ["开箱即用"当然可以正常工作,如果您完全更新并且对这个概念实际上会意味着什么感到满意 - 例如默认的重试策略、SSL主机名验证、默认超时等等将不会对我们起作用 - 如果您使用自定义,则必须理解您正在做什么,这在长期来看总是更好的..?])。无论如何,该解决方案也适用于4.x.x之前的版本 - 我将在Garry上面的很好的回答后面添加一个示例。使用maven构建,并且通常适应压缩响应,我已经添加了

  <dependency>
      <groupId>org.brotli</groupId>
      <artifactId>dec</artifactId>
      <version>0.1.2</version>
  </dependency>

我在我的pom.xml文件中添加了相应的依赖。然后,为了处理这三种常见的压缩方法(gzip、deflate和brotli),我在设置自定义Apache HttpClient时添加了拦截器 - 就像这样:

private static final String GZIP = "gzip";
private static final String DEFLATE = "deflate";
private static final String BR = "br";
private static final String ACCEPT_ENCODING = "Accept-Encoding";
private static final String COMMA_SPACE = ", ";
private static final String SUPPORTED_COMPRESSION_VARIANTS = new StringBuilder(GZIP).append(COMMA_SPACE).append(DEFLATE).append(COMMA_SPACE).append(BR).toString();

..
                   HttpClients.custom()..
                   .addInterceptorFirst((HttpRequestInterceptor) (request, context) -> { // add accepting compressed headers _always_
                    if (!request.containsHeader(ACCEPT_ENCODING)) {
                        request.addHeader(ACCEPT_ENCODING, SUPPORTED_COMPRESSION_VARIANTS);
                    }
                    })
                    .addInterceptorFirst((HttpResponseInterceptor) (response, context) -> {
                    HttpEntity entity = response.getEntity();
                    Header ceheader = entity != null ? entity.getContentEncoding() : null;
                    if (ceheader != null) {
                        HeaderElement[] codecs = ceheader.getElements();
                        for (int i = 0; i < codecs.length; i++) {
                            if (codecs[i].getName().equalsIgnoreCase(GZIP)) { // handling gzip
                                response.setEntity(new GzipDecompressingEntity(response.getEntity()));
                            } else if (codecs[i].getName().equalsIgnoreCase(DEFLATE)) { // handling deflate
                                response.setEntity(new DeflateDecompressingEntity(response.getEntity()));
                            } else if (codecs[i].getName().equalsIgnoreCase(BR)) { // handling brotli
                                try (BufferedReader br =
                                             new BufferedReader(new InputStreamReader(new BrotliInputStream(response.getEntity().getContent())))) {
                                     response.setEntity(new StringEntity(br.lines().collect(Collectors.joining())));
                                }
                            }
                        }
                    }
                  }).build();

因此,对于这些内容,其接受标头将始终添加到传出请求中,并且响应拦截器会处理压缩响应。运行良好。

1

这里是使用Java Apache-Http-Client库的Scala示例代码。

 def createCloseableHttpClient(): CloseableHttpClient = {
    val builder: HttpClientBuilder = HttpClientBuilder.create
    val closableClient = builder.build()
    closableClient
  }

  def postData(data: String): Unit = {
    val entity = EntityBuilder.create()
      .setText(data)
      .setContentType(ContentType.TEXT_PLAIN)
      .gzipCompress()
      .build()
    val post = new HttpPost(postURL + endPoint)
    post.setEntity(entity)
    post.setHeader("Content-Type", "application/gzip")
    val client = createCloseableHttpClient()
    client.execute(post)
    client.close()
  }

-1

它不支持开箱即用,但您可以通过调用返回的HttpResponse实体来将其转换为未压缩的实体。

val entity = new GzipDecompressingEntity(response.getEntity)

然后像往常一样继续使用entity.getContent


-3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接