34

库 Apache Commons HttpClient 是否支持 Gzip?我们想在我们的 Apache 服务器上使用启用 gzip 压缩来加速客户端/服务器通信(我们有一个 php 页面,允许我们的 Android 应用程序与服务器同步文件)。

4

8 回答 8

30

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

于 2010-05-07T16:35:13.033 回答
19

如果您的服务器能够提供 GZIPped 内容,那么您只需使用 Apache Http 客户端 4.1

org.apache.http.impl.client.ContentEncodingHttpClient

它是 的子类DefaultHttpClient

该客户端还将添加标头,说明它接受 GZIPped 内容。

于 2011-08-04T12:49:04.477 回答
9

从 4.1 开始,Apache HttpClients 处理请求和响应压缩。

  • 您无需压缩请求,无需在请求标头中设置任何“Accept-Encoding”。
  • 它也会自动处理响应解压,无需处理响应解压。
  • 直到 4.3 它处理 gzip 和 deflate。您可以在此处ResponseContentEncoding查看api 文档。

只需使用:

HttpClients.custom()

它使用:

HttpClientBuilder.create()

如果你想签入库 gotoHttpClientBuilder它使用RequestAcceptEncoding&ResponseContentEncoding

您可以通过“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();
于 2017-10-24T12:29:31.017 回答
8

它不支持这种开箱即用的功能,而且似乎不太可能将其添加到 HttpClient 3.x 中(请参阅此处相当讨厌的 JIRA 问题)。但是,您可以通过添加自定义请求阅读器和手动请求/响应流处理来做到这一点,分层在基本库之上,但这很繁琐。

看来您可以使用 HttpClient 4 来做到这一点,但并非不费吹灰之力。

相当粗制滥造,如果你问我,这东西真的应该比它更容易。

于 2010-05-05T21:59:35.667 回答
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()
  }
于 2017-05-16T13:08:56.067 回答
0

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

val entity = new GzipDecompressingEntity(response.getEntity)

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

于 2016-05-14T20:56:40.010 回答
0

对于那些(像我一样)由于其他原因无法更新到 Apache 4.xx 并且需要拥有他们的 Apache 的人(顺便说一下,下面的 4.3.6 版本首先实现了它显然不支持“开箱即用”,尽管这可能是当然,因为我们总是使用对我们的 httpclients 有其他特定要求的自定义客户端 [“开箱即用”当然可以,如果您完全了解最新信息并且可以接受这个概念的实际含义 - 例如默认重试策略,SSL 主机名验证,默认超时等对我们不起作用- 如果您使用自定义,则必须了解你在做什么,从长远来看,这总是更好的......?])。无论如何,该解决方案也适用于 4.xx 之前的版本——我在上面 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 SUPPORTED_COMPRESSION_VARIANTS = new StringBuilder(GZIP).append(COMMA_SPACE).append(DEFLATE).append(COMMA_SPACE).append(BR).toString();
private static final String COMMA_SPACE = ", ";
..
                   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();

所以 - 这些的接受标头将始终添加到传出请求中,并且压缩响应由响应拦截器处理。工作正常。

于 2022-02-01T22:27:06.300 回答
-1

自定义协议拦截器也可能有所帮助。

免责声明:我还没有尝试过。

于 2014-03-27T02:17:45.720 回答