2017-04-26 69 views
0

我正在开发一个应用程序,使用Retrofit 2向API请求。这个API是ASP.NET,它是用gzip和编码压缩和解为Base64,如下面的代码:修改响应主体改造2.2拦截器

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()); 
     } 
    } 
} 

现在,我需要在我的Android应用程序做的就是从改造的响应,从解码Base64并解压缩。我试图用Interceptor来做,但我没有成功。

这是我从服务H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA收到的回复,解码和解压缩回复,我们有true

是否有人知道该怎么办呢?

回答

2

这很容易。下面的代码使用Google Guava来解码Base64字符流和Google Gson以反序列化JSON内容。

请看下面的测试服务接口:

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(); 
    } 

} 

此实现也应该检测内容MIME:

interface IService { 

    @GET("/") 
    Call<String> get(); 

} 

现在你可以使用模板方法设计模式,实现你的拦截器响应输入流变压器基地类型为了不做错误的转换,但你可以轻松地实现它。因此,这里也是两个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)); 
    } 

} 
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); 
    } 

} 

并对其进行测试:

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); 
} 

注意getFakeContentInterceptor返回假的拦截器,它总是返回H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA,使baseUrl不甚至有一个真正的URL。输出:

真正

+0

再次,你帮了我很多,非常感谢你:再次d – jackcar

+0

@jackcar,真的吗?哈,不客气! :) –