-
-
Save premnirmal/8526542 to your computer and use it in GitHub Desktop.
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)); | |
} | |
} |
hi FrancoSabadini, you mean you don't need to unzip manually? thanks.
FrancoSabadini is absolutely right. "Accept-Encoding gzip" is already set using Volley.
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?
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));
}
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;
}
}
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
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.