Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

commented May 5, 2014

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

This comment has been minimized.

Copy link

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?

@proverbface

This comment has been minimized.

Copy link

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));
@FrancoSabadini

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Jul 1, 2015

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

@Ryan4GT

This comment has been minimized.

Copy link

commented Aug 26, 2015

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

@titoleiva

This comment has been minimized.

Copy link

commented Oct 29, 2015

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?

@zerokol

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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
You can’t perform that action at this time.