欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Okhttp3请求网络开启Gzip压缩

程序员文章站 2022-03-31 11:43:24
前沿 首先OkHttp3是支持Gzip解压缩的,不过我们要明白,它是支持我们在发起请求的时候自动加入header,Accept-Encoding: gzip,而我们的服务器返回的时候header中有Content-Encoding: gzip。 关于更多深入的内容呢,可以参考阅读下面这篇文章,讲的非 ......

前沿

首先OkHttp3是支持Gzip解压缩的,不过我们要明白,它是支持我们在发起请求的时候自动加入header,Accept-Encoding: gzip,而我们的服务器返回的时候header中有Content-Encoding: gzip
关于更多深入的内容呢,可以参考阅读下面这篇文章,讲的非常好!
聊聊HTTP gzip压缩与常见的Android网络框架

那么,我们在向服务器提交大量数据的时候,希望对post的数据进行gzip压缩,改怎么办?
下边给出方案!

方案

官方采用的是自定义拦截器的方式!
源码在:
okhttp/samples/guide/src/main/java/okhttp3/recipes/RequestBodyCompression.java
废话不多说,直接上代码:

 1 import java.io.IOException;
 2 
 3 import okhttp3.Interceptor;
 4 import okhttp3.MediaType;
 5 import okhttp3.Request;
 6 import okhttp3.RequestBody;
 7 import okhttp3.Response;
 8 import okio.BufferedSink;
 9 import okio.GzipSink;
10 import okio.Okio;
11 
12 public class GzipRequestInterceptor implements Interceptor {
13     @Override
14     public Response intercept(Chain chain) throws IOException {
15         Request originalRequest = chain.request();
16         if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
17             return chain.proceed(originalRequest);
18         }
19 
20         Request compressedRequest = originalRequest.newBuilder()
21                 .header("Content-Encoding", "gzip")
22                 .method(originalRequest.method(), gzip(originalRequest.body()))
23                 .build();
24         return chain.proceed(compressedRequest);
25     }
26 
27     private RequestBody gzip(final RequestBody body) {
28         return new RequestBody() {
29             @Override
30             public MediaType contentType() {
31                 return body.contentType();
32             }
33 
34             @Override
35             public long contentLength() {
36                 return -1; // 无法提前知道压缩后的数据大小
37             }
38 
39             @Override
40             public void writeTo(BufferedSink sink) throws IOException {
41                 BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
42                 body.writeTo(gzipSink);
43                 gzipSink.close();
44             }
45         };
46     }
47 }

然后构建OkhttpClient的时候,添加拦截器:

OkHttpClient okHttpClient = new OkHttpClient.Builder() 
    .addInterceptor(new GzipRequestInterceptor())//开启Gzip压缩
    ...
    .build();

后记

如果需要带有内容长度content-length的,可以查看这个issue:
Here’s the full gzip interceptor with content length, to whom it may concern:

参考:https://blog.csdn.net/tq08g2z/article/details/77311579