Skip to content

Instantly share code, notes, and snippets.

@premnirmal
Last active December 20, 2022 06:07
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save premnirmal/8526542 to your computer and use it in GitHub Desktop.
Save premnirmal/8526542 to your computer and use it in GitHub Desktop.
Parse GZip responses using volley
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.StringRequest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
public class GZipRequest extends StringRequest {
public GZipRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(method, url, listener, errorListener);
}
public GZipRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(url, listener, errorListener);
}
// parse the gzip response using a GZIPInputStream
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String output = ""; // note: better to use StringBuilder
try {
final GZIPInputStream gStream = new GZIPInputStream(new ByteArrayInputStream(response.data));
final InputStreamReader reader = new InputStreamReader(gStream);
final BufferedReader in = new BufferedReader(reader);
String read;
while ((read = in.readLine()) != null) {
output += read;
}
reader.close();
in.close();
gStream.close();
} catch (IOException e) {
return Response.error(new ParseError());
}
return Response.success(output, HttpHeaderParser.parseCacheHeaders(response));
}
}
@scottagarman
Copy link

I added something like this:

        String encoding = response.headers.get("Content-Encoding");
        if(encoding != null && encoding.equals("gzip")) {

I'm not sure if there is a better way to do this check somewhere else but my servers don't always gzip things.

@RdlP
Copy link

RdlP commented Sep 21, 2014

I am having problem with GZIP in volley I comment my problem here: http://stackoverflow.com/questions/25960815/accept-encoding-in-volley-doesnt-response-with-content-encoding know you what is happen?

Copy link

ghost commented Oct 19, 2014

Hi guys, that code is a quite slow because it does not use StringBuilder and the size of the BufferedReader is the default one, which is 8192 bytes.

StringBuilder output = new StringBuilder();
try
 {
         GZIPInputStream gStream = new GZIPInputStream( new ByteArrayInputStream( response.data ) );
         InputStreamReader reader = new InputStreamReader( gStream );
         BufferedReader in = new BufferedReader( reader, 16384 );

         String read;

         while ( ( read = in.readLine() ) != null )
         {
                output.append( read ).append( "\n" );
         }
         reader.close();
         in.close();
         gStream.close();
 }
 catch ( IOException e )
 {
         return Response.error( new ParseError() );
 }

return Response.success(output.toString(), HttpHeaderParser.parseCacheHeaders(response));

@francos
Copy link

francos commented Feb 16, 2015

Gzip worked out of the box for me using Volley, the secret is to not set the "Accept-Encoding gzip" header manually, since it is already set by HttpUrlConnection. If that header is set manually then the unzipping fails for whatever reason. You can verify this by using Charles Proxy or Fiddler and seeing the request headers.

@JadenGu
Copy link

JadenGu commented Jul 1, 2015

hi FrancoSabadini, you mean you don't need to unzip manually? thanks.

@Ryan4GT
Copy link

Ryan4GT commented Aug 26, 2015

FrancoSabadini is absolutely right. "Accept-Encoding gzip" is already set using Volley.

@titoleiva
Copy link

If is already set, how do you send/receive zipped requests/responses? How does the server know that I'm doing explicitly a GZIP request, so it have to send me a gzipped response? I'm trying to use this code, that seems quite good, but I always get a server error when I do a GET or a POST. For the POST, I'm overriding the getBody() method and converting the JSON params into a String and then into a byte array. Is this a good approach?

@alvesoaj
Copy link

alvesoaj commented Jul 20, 2016

No, volley not set "Accept-Encoding" manually! Do that:

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    Map<String, String> params = new HashMap<>();
    params.putAll(super.getHeaders());
    params.put("Accept-Encoding", "gzip,deflate");
    return params;
}

to decompress, the best bet is proverbface' answer:

@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
    StringBuilder output = new StringBuilder();
    try {
        GZIPInputStream gStream = new GZIPInputStream(new ByteArrayInputStream(response.data));
        InputStreamReader reader = new InputStreamReader(gStream);
        BufferedReader in = new BufferedReader(reader, 16384);

        String read;

        while ((read = in.readLine()) != null) {
            output.append(read).append("\n");
        }
        reader.close();
        in.close();
        gStream.close();
    } catch (IOException e) {
        return Response.error(new ParseError());
    }

    return Response.success(output.toString(), HttpHeaderParser.parseCacheHeaders(response));
}

@achavhan
Copy link

achavhan commented Aug 3, 2016

I have new working code set

import com.android.volley.NetworkResponse;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.StringRequest;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.InflaterInputStream;

/**

  • Created by Amol on 03-08-2016.
    */
    public class GZipRequest extends StringRequest {

    public GZipRequest(int method, String url, Response.Listener listener, Response.ErrorListener errorListener) {
    super(method, url, listener, errorListener);
    }

    public GZipRequest(String url, Response.Listener listener, Response.ErrorListener errorListener) {
    super(url, listener, errorListener);
    }

    @OverRide
    protected Response parseNetworkResponse(NetworkResponse response) {
    return Response.success(unzipString(response.data), HttpHeaderParser.parseCacheHeaders(response));
    }

    public static String unzipString(byte[] zbytes) {
    String charsetName = "ISO-8859-1";
    String unzipped = null;
    try {
    // Add extra byte to array when Inflater is set to true
    byte[] input = new byte[zbytes.length + 1];
    System.arraycopy(zbytes, 0, input, 0, zbytes.length);
    input[zbytes.length] = 0;
    ByteArrayInputStream bin = new ByteArrayInputStream(input);
    InflaterInputStream in = new InflaterInputStream(bin);
    ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
    int b;
    while ((b = in.read()) != -1) {
    bout.write(b);
    }
    bout.close();
    unzipped = bout.toString(charsetName);
    } catch (IOException e) {
    e.printStackTrace();
    }
    return unzipped;
    }

}

@velnias75
Copy link

velnias75 commented Oct 6, 2019

Dear @scottagarman,

I added something like this:

        String encoding = response.headers.get("Content-Encoding");
        if(encoding != null && encoding.equals("gzip")) {

I'm not sure if there is a better way to do this check somewhere else but my servers don't always gzip things.

Just my two cents, you could write also if("gzip".equals(response.headers.get("Content-Encoding"))) {
Saves you both the check on null and the additional String object.

BTW: you can find my implementation for a JsonArrayRequest here: GZipJsonArrayRequest.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment