pako.js对数据进行gzip压缩传递到后台解析,解决数据量大的请求问题

来源:互联网 发布:美橙域名查询 编辑:程序博客网 时间:2024/05/16 06:02

本文来源于简书:使用gzip压缩请求正文

附参照文章所实现的gzipdemo
下载线路1
备用线路2

demo运行效果图如下:
demo运行效果图如下:

实现思路

在前台对请求正文使用 pako_deflate.js 进行本地 gzip 格式压缩
在后台使用 Java 对请求正文进行解压

操作环境

  • jdk 1.8.0_77
  • idea 2016.2.1
  • maven 3.3.9

项目依赖

  • commons-io-2.5 (简化IO操作)
  • json-lib-2.4 (处理请求正文中的参数)
  • spring-webmvc-4.3.4.RELEASE
  • pako_deflate-1.0.3.js (JS文本压缩工具类)

JS 压缩请求正文

因为只在前台进行压缩,所以只需引用 pako 的压缩专用文件 pako_deflate.min.js
又因为我在项目中主要使用 jQuery 发送 Ajax 请求,所以引入 jQuery

<script src="jquery-2.2.4.min.js"></script><script src="pako_deflate.min.js"></script>

将发送的参数转换为 JSON 字符串

var params = encodeURIComponent(JSON.stringify({    title: "标题",    content: "内容"}));

gzip 虽然能极大的压缩请求正文.但是如果内容过小,压缩后内容反而会增大,经测试,对于 params.length 大于 1000 的文本压缩效果能够达到 60% 以上,所以在压缩前,需要对内容进行判断

var params = encodeURIComponent(JSON.stringify({    title: title,    content: content}));var compressBeginLen = params.length;if (compressBeginLen > 1000) {    //对 JSON 字符串进行压缩    // pako.gzip(params) 默认返回一个 Uint8Array 对象,如果此时使用 Ajax 进行请求,参数会以数组的形式进行发送    // 为了解决该问题,添加 {to: "string"} 参数,返回一个二进制的字符串    params = pako.gzip(params, {to: "string"});}$.ajax({    url: "/gzip",    data: params,    dataType: "text",    type: "post",    headers: {        //如果 compressBeginLen 大于 1000,标记此次请求的参数使用了 gzip 压缩        "Content-Encoding": params.length>1000?"gzip":""    },    success: function (data) {        //dosomething    }})

Java 解压请求正文

首先获取 Content-Encoding 请求头,根据该请求头中的内容进行逻辑处理

@ResponseBody@RequestMapping(value = "/gzip")public String gzip(HttpServletRequest request) {    String params = "";    try {        //获取 Content-Encoding 请求头        String contentEncoding = request.getHeader("Content-Encoding");        if (contentEncoding != null && contentEncoding.equals("gzip")) {            //获取输入流            BufferedReader reader = request.getReader();            //将输入流中的请求实体转换为byte数组,进行gzip解压            byte[] bytes = IOUtils.toByteArray(reader, "iso-8859-1");            //对 bytes 数组进行解压            params = GZIPUtil.uncompress(bytes);        } else {            BufferedReader reader = request.getReader();            params = IOUtils.toString(reader);        }        if (params != null && params.trim().length() > 0) {            //因为前台对参数进行了 url 编码,在此进行解码            params = URLDecoder.decode(params, "utf-8");            //将解码后的参数转换为 json 对象            JSONObject json = JSONObject.fromObject(params);            //从 json 对象中获取参数进行后续操作            System.out.println("title:\t" + json.getString("title"));            System.out.println("content:\t" + json.getString("content"));        }    } catch (IOException e) {        e.printStackTrace();    }    return params;}

Java gzip 解压方法 GZIPUtil.uncompress 参考 Java 使用 GZIP 进行压缩和解压缩(GZIPOutputStream,GZIPInputStream) 一文而成

/** * 解压gzip格式byte数组 * @param bytes gzip格式byte数组 * @param charset 字符集 */public static String uncompress(byte[] bytes, String charset) {    if (bytes == null || bytes.length == 0) {        return null;    }    ByteArrayOutputStream byteArrayOutputStream = null;    ByteArrayInputStream byteArrayInputStream = null;    GZIPInputStream gzipInputStream = null;    try {        byteArrayOutputStream = new ByteArrayOutputStream();        byteArrayInputStream = new ByteArrayInputStream(bytes);        gzipInputStream = new GZIPInputStream(byteArrayInputStream);        //使用org.apache.commons.io.IOUtils 简化流的操作        IOUtils.copy(gzipInputStream, byteArrayOutputStream);        return byteArrayOutputStream.toString(charset);    } catch (IOException e) {        e.printStackTrace();    } finally {        //释放流资源        IOUtils.closeQuietly(gzipInputStream);        IOUtils.closeQuietly(byteArrayInputStream);        IOUtils.closeQuietly(byteArrayOutputStream);    }    return null;}

另外 Jerry Qu 实现了一个服务器使用 Node.js 解压的 DEMO 并提供 deflate,zlib,gzip 三种压缩,解压方式
以上完整代码可在 gzip 项目中查看




0 0
原创粉丝点击