jac*_*car 2 java base64 gzip interceptor retrofit
我正在使用Retrofit 2开发一个应用程序以请求API。该API位于ASP.NET中,并且使用GZip压缩并编码为Base64,如以下代码所示:
private static string Compress(string conteudo)
{
Encoding encoding = Encoding.UTF8;
byte[] raw = encoding.GetBytes(conteudo);
using (var memory = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(memory, CompressionMode.Compress, true))
{
gzip.Write(raw, 0, raw.Length);
}
return Convert.ToBase64String(memory.ToArray());
}
}
private static string Decompress(string conteudo)
{
Encoding encoding = Encoding.UTF8;
var gzip = Convert.FromBase64String(conteudo);
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
int size = gzip.Length;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return encoding.GetString(memory.ToArray());
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我需要在Android应用中执行的操作是从Retrofit获取响应,从Base64解码并解压缩。我尝试使用进行操作Interceptor,但没有成功。
这是我从服务中收到H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA的对我们进行解码和解压缩响应的返回true。
有人知道怎么做吗?
这简单。下面的代码使用Google Guava来解码Base64字符流,并使用Google Gson反序列化JSON内容。
考虑以下测试服务接口:
interface IService {
@GET("/")
Call<String> get();
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用模板方法设计模式来实现拦截器响应输入流转换器基础:
abstract class AbstractTransformingDecodingInterceptor
implements Interceptor {
protected abstract InputStream transformInputStream(InputStream inputStream)
throws IOException;
@Override
@SuppressWarnings("resource")
public final Response intercept(final Chain chain)
throws IOException {
final Request request = chain.request();
final Response response = chain.proceed(request);
final ResponseBody body = response.body();
return response.newBuilder()
.body(ResponseBody.create(
body.contentType(),
body.contentLength(),
Okio.buffer(Okio.source(transformInputStream(body.byteStream())))
))
.build();
}
}
Run Code Online (Sandbox Code Playgroud)
此实现还应该检测内容MIME类型,以免进行错误的转换,但是您可以自己轻松实现它。因此,这也是Base64和GZip的两个转换拦截器:
final class Base64DecodingInterceptor
extends AbstractTransformingDecodingInterceptor {
private static final Interceptor base64DecodingInterceptor = new Base64DecodingInterceptor();
private Base64DecodingInterceptor() {
}
static Interceptor getBase64DecodingInterceptor() {
return base64DecodingInterceptor;
}
@Override
protected InputStream transformInputStream(final InputStream inputStream) {
return BaseEncoding.base64().decodingStream(new InputStreamReader(inputStream));
}
}
Run Code Online (Sandbox Code Playgroud)
final class GzipDecodingInterceptor
extends AbstractTransformingDecodingInterceptor {
private static final Interceptor gzipDecodingInterceptor = new GzipDecodingInterceptor();
private GzipDecodingInterceptor() {
}
static Interceptor getGzipDecodingInterceptor() {
return gzipDecodingInterceptor;
}
@Override
protected InputStream transformInputStream(final InputStream inputStream)
throws IOException {
return new GZIPInputStream(inputStream);
}
}
Run Code Online (Sandbox Code Playgroud)
并测试一下:
private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(getGzipDecodingInterceptor())
.addInterceptor(getBase64DecodingInterceptor())
.addInterceptor(getFakeContentInterceptor())
.build();
private static final Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://whatever")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
private static final IService service = retrofit.create(IService.class);
public static void main(final String... args)
throws IOException {
final String body = service.get().execute().body();
System.out.println(body);
}
Run Code Online (Sandbox Code Playgroud)
请注意,getFakeContentInterceptor返回的是一个伪造的拦截器,该拦截器总是返回,H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA因此baseUrl甚至没有真实的URL。输出:
真正
| 归档时间: |
|
| 查看次数: |
5072 次 |
| 最近记录: |