关于ETag和Gzip的基本认知和使用
程序员文章站
2022-03-11 16:35:07
...
题引:为了提升用户体验,同时减轻服务器压力和降低网络带宽,技术总监和技术经理决定对APP做缓存和压缩处理,包括图片的三级缓存(这里不讨论)和网络请求的数据缓存和压缩
- ETag的基本认识
- ETag的基本使用
- Gzip的基本认识
- Gzip的基本使用
- 判读服务器是否返回压缩数据的方式
- 服务端Nginx配置ETag和Gzip冲突的解决方案
- Refer
一、ETag的基本认识
以下四篇文章讲解的都是ETag的基本知识:
二、ETag的基本使用
ETag的使用就Android客户端来说,大概有两个步骤:
- Header添加If-None-Match/ETag信息
- 执行请求返回响应体后做相应的缓存处理
三、Gzip的基本认识
HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来减少文件大小,减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间。
四、Gzip的基本使用
Gzip的基本使用就Android客户端来说,大概有两个步骤:
- Header添加Accept-Encoding属性值为gzip
- 执行请求返回响应体后做相应的解压处理
附样板代码如下:
1、获取HttpClient
private static DefaultHttpClient getHttpClient() {
DefaultHttpClient httpClient = new DefaultHttpClient();
// 设置 连接超时时间
httpClient.getParams().setParameter(
HttpConnectionParams.CONNECTION_TIMEOUT, TIMEOUT_CONNECTION);
// 设置 读数据超时时间
httpClient.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT,
TIMEOUT_SOCKET);
// 设置 字符集
httpClient.getParams().setParameter("http.protocol.content-charset",
UTF_8);
return httpClient;
}
2、获取HttpPost
private static HttpPost getHttpPost(String url) {
HttpPost httpPost = new HttpPost(url);
// 设置 请求超时时间
httpPost.getParams().setParameter(HttpConnectionParams.SO_TIMEOUT,
TIMEOUT_SOCKET);
httpPost.setHeader("Connection", "Keep-Alive");
httpPost.addHeader("Accept-Encoding", "gzip");
return httpPost;
}
3、访问网络及解压
public static InputStream http_post_return_byte(String url,
Map<String, String> params) throws AppException {
DefaultHttpClient httpclient = null;
HttpPost post = null;
HttpResponse response = null;
StringBuilder sb = null;
StringEntity stringEntity = null;
try {
httpclient = getHttpClient();
post = getHttpPost(url);
sb = new StringBuilder();
if (params != null && !params.isEmpty()) {
Logger.d("In http_post the url is get here");
for (Entry<String, String> entry : params.entrySet()) {
sb.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(),
HTTP.UTF_8)).append("&");
}
sb.deleteCharAt(sb.lastIndexOf("&"));
Logger.d("In http_post the url is " + url + " and params is "
+ sb.toString());
stringEntity = new StringEntity(sb.toString());
stringEntity
.setContentType("application/x-www-form-urlencoded");
post.setEntity(stringEntity);
}
response = httpclient.execute(post);
int statusCode = response.getStatusLine().getStatusCode();
Logger.d("statusCode is " + statusCode);
if (statusCode != HttpStatus.SC_OK) {
throw AppException.http(statusCode);
}
InputStream is = response.getEntity().getContent();
Header contentEncoding = response
.getFirstHeader("Content-Encoding");
if (contentEncoding != null
&& contentEncoding.getValue().equalsIgnoreCase("gzip")) {
is = new GZIPInputStream(new BufferedInputStream(is));
}
return is;
} catch (ClientProtocolException e) {
e.printStackTrace();
throw AppException.http(e);
} catch (IOException e) {
e.printStackTrace();
throw AppException.network(e);
} finally {
/*
* if (!post.isAborted()) {
*
* post.abort(); } httpclient = null;
*/
}
}
五、判断网络返回的数据是否经过压缩
- 从Http 技术细节上讲,request头中如果有 “Accept-Encoding”,”gzip”,response中就有返回头”Content-Encoding”:”gzip”,因此可以通过判读响应体是否有Content-Encoding属性,并且其值为gzip。
- gzip流前两个字节是0x1f8b,因此可通过判断输入流的前两个字节是否为0x1f8b。
附具体代码如下:
private String getJsonStringFromGZIP(HttpResponse response) {
String jsonString = null;
try {
InputStream is = response.getEntity().getContent();
BufferedInputStream bis = new BufferedInputStream(is);
bis.mark(2);
// 取前两个字节
byte[] header = new byte[2];
int result = bis.read(header);
// reset输入流到开始位置
bis.reset();
// 判断是否是GZIP格式
int headerData = getShort(header);
// Gzip 流 的前两个字节是 0x1f8b
if (result != -1 && headerData == 0x1f8b) {
LogUtil.d("HttpTask", " use GZIPInputStream ");
is = new GZIPInputStream(bis);
} else {
LogUtil.d("HttpTask", " not use GZIPInputStream");
is = bis;
}
InputStreamReader reader = new InputStreamReader(is, "utf-8");
char[] data = new char[100];
int readSize;
StringBuffer sb = new StringBuffer();
while ((readSize = reader.read(data)) > 0) {
sb.append(data, 0, readSize);
}
jsonString = sb.toString();
bis.close();
reader.close();
} catch (Exception e) {
LogUtil.e("HttpTask", e.toString(),e);
}
LogUtil.d("HttpTask", "getJsonStringFromGZIP net output : " + jsonString );
return jsonString;
}
private int getShort(byte[] data) {
return (int)((data[0]<<8) | data[1]&0xFF);
}
六、服务端Nginx配置ETag和Gzip冲突的解决方案
以下三篇文章都涉及到ETag和Gzip冲突的解决方案:
七、Refer
下一篇: 动态合并table单元格(行列)