Skip to content

Instantly share code, notes, and snippets.

@premnirmal
Last active December 20, 2022 06:07
Show Gist options
  • 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));
}
}
@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