关于ETag和Gzip的基本认知和使用

来源:互联网 发布:大数据洞察有哪些特色 编辑:程序博客网 时间:2024/05/20 12:46

题引:为了提升用户体验,同时减轻服务器压力和降低网络带宽,技术总监和技术经理决定对APP做缓存和压缩处理,包括图片的三级缓存(这里不讨论)和网络请求的数据缓存和压缩

  • ETag的基本认识
  • ETag的基本使用
  • Gzip的基本认识
  • Gzip的基本使用
  • 判读服务器是否返回压缩数据的方式
  • 服务端Nginx配置ETag和Gzip冲突的解决方案
  • Refer

一、ETag的基本认识

以下四篇文章讲解的都是ETag的基本知识:

  1. 客户端HTTP协议缓存的研究
  2. If-Modified-Since & If-None-Match
  3. REST笔记(五):你应该知道的HTTP头——ETag
  4. http协议-缓存统制:etag If-None-Match / Last-Modified If-Modified-Since

二、ETag的基本使用

ETag的使用就Android客户端来说,大概有两个步骤:

  1. Header添加If-None-Match/ETag信息
  2. 执行请求返回响应体后做相应的缓存处理

三、Gzip的基本认识

HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来减少文件大小,减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间。

四、Gzip的基本使用

Gzip的基本使用就Android客户端来说,大概有两个步骤:

  1. Header添加Accept-Encoding属性值为gzip
  2. 执行请求返回响应体后做相应的解压处理
附样板代码如下:

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;              */          }  }  

五、判断网络返回的数据是否经过压缩

  1. 从Http 技术细节上讲,request头中如果有 “Accept-Encoding”,”gzip”,response中就有返回头”Content-Encoding”:”gzip”,因此可以通过判读响应体是否有Content-Encoding属性,并且其值为gzip。
  2. 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冲突的解决方案:

  1. nginx开启gzip模块后ETAG丢失
  2. nginx - missing etag when gzip is used
  3. Nginx如何开启ETag,提高访问速度

七、Refer

  1. Android中使用gzip传递数据
  2. Android开发中网络请求的压缩 ── GZip的使用
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米手机重置后开机黑屏怎么办 dnf夏日套光环选错了怎么办 ios6微信版本低登录不了怎么办 捡了一个苹果手机有id怎么办 外阴长了个包出血很痛怎么办 腿上烫成泡了泡泡破了掉皮了怎么办 脚上的脚气小泡泡破了怎么办 吃鸡使用改名卡改名符号怎么办 爱派平板电脑密码忘了怎么办 电脑优酷下载总显示未知错误怎么办 文本文档打开时显字符丢失怎么办 系统文件过大无法放进u盘怎么办 淘宝上买的密钥激活不了怎么办 苹果手机玩游戏屏幕卡住不动怎么办 电脑系统安装好一排英文字怎么办 赴日签证申请表写错了怎么办 不知道自己想要做什么工作怎么办 三星note4微信出现闪退怎么办 魅蓝note6手机自动闪退怎么办 苹果6s系统内存占用量过大怎么办 想在一年通过会计初级和中级怎么办 特殊岗位退休档察写的力工怎么办 面试时期望工资说低了。怎么办 面试时期望薪资写低了怎么办 高考后比一模差了80分怎么办 戒了烟我不习惯没有你我怎么办 没有你我不习惯没有你我怎么办 做什么都没兴趣嫌麻烦怎么办 快递还在路上就确认收货了怎么办 微信显示时间与手机不符怎么办 微信提示银行卡预留手机不符怎么办 得了湿疹后吃了海鲜严重了怎么办 看到小区街道乱扔的垃圾你会怎么办 去韩国干服务员不会讲韩语怎么办 华为手机键盘变英文字母大了怎么办 淘宝申请售后卖家余额不足怎么办 发票名称少写了一个字怎么办 微博数量与实际数量不一致怎么办 在淘宝中要买的商品卖完了怎么办 病因写错了保险不报销怎么办? 上学期间保险名字写错了怎么办