前言
首先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
廢話不多說,直接上代碼:
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSink;
import okio.GzipSink;
import okio.Okio;
public class GzipRequestInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")
.method(originalRequest.method(), gzip(originalRequest.body()))
.build();
return chain.proceed(compressedRequest);
}
private RequestBody gzip(final RequestBody body) {
return new RequestBody() {
@Override
public MediaType contentType() {
return body.contentType();
}
@Override
public long contentLength() {
return -; // 無法提前知道壓縮後的資料大小
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
body.writeTo(gzipSink);
gzipSink.close();
}
};
}
}
然後建構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: