2017-04-26 1 views
0

API를 요청하려면 Retrofit 2를 사용하는 앱을 개발하고 있습니다. 이 API는 ASP.NET에 그리고 아래의 코드처럼, Base64로에 Gzip으로 인코딩으로 압축하는됩니다 : 내가 내 안드로이드 응용 프로그램에서해야 할 것은, 개조의 응답을 얻을에서 디코딩하고, 지금응답 본문 수정 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()); 
     } 
    } 
} 

Base64로 풀고 압축을 풉니 다. 나는 Interceptor을 사용하여 그것을 시도했지만 성공하지 못했습니다.

이것은 서비스 H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA에서받은 응답이며, 응답을 디코딩하고 압축을 해제하면 true이됩니다.

누구나 어떻게 해야할지 알고 있습니까?

답변

2

쉽습니다. 아래 코드는 Google 구아바를 사용하여 Base64 문자 스트림을 디코딩하고 Google Gson을 사용하여 JSON 콘텐츠를 비 직렬화합니다. 이 구현은 또한 컨텐츠 MIME를 감지합니다

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

} 

:

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

} 

는 그리고 테스트 : getFakeContentInterceptor 항상 H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA 그래서 baseUrl하지 않는 것을 반환하는 가짜 인터셉터를 반환

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

하는 것으로 실제 URL이 있습니다. 출력 :

사실

+0

다시 한번 당신이 저에게 많은 도움 정말 감사합니다 : D – jackcar

+0

@jackcar을 다시 한번, 정말? 하, 천만에! :) –