2009-10-15 32 views
103

Tôi đã liên lạc HTTP với máy chủ web yêu cầu dữ liệu JSON. Tôi muốn nén luồng dữ liệu này với Content-Encoding: gzip. Có cách nào tôi có thể đặt Accept-Encoding: gzip trong HttpClient của tôi không? Tìm kiếm gzip trong Tham chiếu Android không hiển thị bất kỳ nội dung nào liên quan đến HTTP, như bạn có thể thấy here.Android: Giao tiếp HTTP nên sử dụng "Accept-Encoding: gzip"

+1

[Android-WebRequest] (https://github.com/delight-im/Android-WebRequest) hỗ trợ GZIP và các phản hồi không nén tự động, ví dụ: với 'new WebRequest(). get(). to (" http://www.example.com/ ") .askForGzip (đúng) .executeSync()'. Cụ thể, phương thức [parseResponse (...)] (https://github.com/delight-im/Android-WebRequest/blob/master/src/im/delight/android/webrequest/WebRequest.java) phải là những gì Bạn đang tìm. – caw

Trả lời

168

Bạn nên sử dụng tiêu đề http để chỉ ra một kết nối có thể chấp nhận gzip dữ liệu được mã hóa, ví dụ:

HttpUriRequest request = new HttpGet(url); 
request.addHeader("Accept-Encoding", "gzip"); 
// ... 
httpClient.execute(request); 

Kiểm tra phản ứng để mã hóa nội dung:

InputStream instream = response.getEntity().getContent(); 
Header contentEncoding = response.getFirstHeader("Content-Encoding"); 
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { 
    instream = new GZIPInputStream(instream); 
} 
+6

Đó là một câu trả lời tuyệt vời và rất hữu ích với tất cả các chi tiết tôi cần. Cảm ơn rất nhiều. Một bình luận: thay vì addHeader, tôi sử dụng setHeader. Từ những gì tôi hiểu, điều này sẽ ghi đè "Accept-Encoding" hiện có nếu có. Không chắc chắn cách tiếp cận nào là đúng/tốt hơn. Để ghi đè lên tiêu đề hiện tại để đảm bảo tiêu đề có giá trị phù hợp hoặc để thêm tiêu đề trong trường hợp có thể có các tiêu đề Accept-Encoding khác song song. – znq

+0

nơi nào bạn đặt trong dòng đó? – Mikey

+7

điều này không gzip yêu cầu, nó chỉ cho máy chủ biết rằng bạn có thể chấp nhận phản hồi gzip'd. –

2

Tôi chưa sử dụng GZip, nhưng tôi cho rằng bạn nên sử dụng luồng đầu vào từ HttpURLConnection hoặc HttpResponseGZIPInputStream chứ không phải một số lớp cụ thể khác.

+0

HTTPURLConnection đã bật gzip theo mặc định. Bạn chỉ cần đảm bảo rằng máy chủ web của bạn có thể trả về các trang gzip. http://developer.android.com/reference/java/net/HttpURLConnection.html Tôi có thể trả lại các trang gzip từ php bằng cách sử dụng ob_start ("ob_gzhandler"); – metric152

13

Tôi nghĩ rằng mẫu mã tại liên kết này thú vị hơn: ClientGZipContentCompression.java

Họ đang sử dụng HttpRequestInterceptorHttpResponseInterceptor

mẫu cho yêu cầu:

 httpclient.addRequestInterceptor(new HttpRequestInterceptor() { 

      public void process(
        final HttpRequest request, 
        final HttpContext context) throws HttpException, IOException { 
       if (!request.containsHeader("Accept-Encoding")) { 
        request.addHeader("Accept-Encoding", "gzip"); 
       } 
      } 

     }); 

mẫu cho câu trả lời:

 httpclient.addResponseInterceptor(new HttpResponseInterceptor() { 

      public void process(
        final HttpResponse response, 
        final HttpContext context) throws HttpException, IOException { 
       HttpEntity entity = response.getEntity(); 
       Header ceheader = entity.getContentEncoding(); 
       if (ceheader != null) { 
        HeaderElement[] codecs = ceheader.getElements(); 
        for (int i = 0; i < codecs.length; i++) { 
         if (codecs[i].getName().equalsIgnoreCase("gzip")) { 
          response.setEntity(
            new GzipDecompressingEntity(response.getEntity())); 
          return; 
         } 
        } 
       } 
      } 

     }); 
+1

Bất kỳ lý do gì khiến bạn cho rằng điều đó thú vị hơn? –

+3

@codingcrow Đây là những gì bạn đang tìm kiếm: _Trong trường hợp cụ thể này, HTTP client được tạo ra có khả năng nén nội dung trong suốt GZIP bằng cách thêm hai interceptor giao thức: một interceptor yêu cầu thêm tiêu đề 'Accept-Encoding: gzip' vào tất cả các yêu cầu gửi đi và interceptor phản ứng tự động mở rộng các thực thể phản hồi nén bằng cách gói chúng với một lớp trang trí không nén. Việc sử dụng các interceptor giao thức làm cho nội dung nén hoàn toàn trong suốt đối với người tiêu dùng của giao diện HttpClient._ – clauziere

+0

[Nguồn] (http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/ Ví dụ/khách hàng/ClientGZipContentCompression.java) – clauziere

33

Nếu bạn đang sử dụng mức API 8 hoặc cao hơn có AndroidHttpClient.

Nó có phương pháp helper như:

public static InputStream getUngzippedContent (HttpEntity entity) 

public static void modifyRequestToAcceptGzipResponse (HttpRequest request) 

dẫn đến nhiều mã ngắn gọn hơn:

AndroidHttpClient.modifyRequestToAcceptGzipResponse(request); 
HttpResponse response = client.execute(request); 
InputStream inputStream = AndroidHttpClient.getUngzippedContent(response.getEntity()); 
+0

Mẹo tốt đẹp modifyRequest & getUngzipped, ngoài ra, tôi cần phải sao chép EntityUtils.toString (HttpEntity) để phân tích luồng không tải là String –

+1

AndroidHttpClient không được chấp nhận ở cấp API 22. –

+0

Đã dành khoảng một giờ để tìm giải pháp tốt nhất. Đây là câu trả lời hay nhất !!! cảm ơn – shift66

0

Trong trường hợp của tôi nó là như thế này:

URLConnection conn = ...; 
InputStream instream = conn.getInputStream(); 
String encodingHeader = conn.getHeaderField("Content-Encoding"); 
if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip")) 
{ 
    instream = new GZIPInputStream(instream); 
} 
Các vấn đề liên quan