前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现

工具介绍:

pako.js 前端压缩解压的库(包含 zlib 和gzip 两种实现,这里只介绍 zlib)

pako 2.0.4 API documentation

Java8+ 原生支持 zlib 和 gzip

业务场景

因为数据太大,网络环境不可控。故前端需要将数据 A 先压缩 变为 a,然后才将 a 发送到 Java 服务器端后处理或存储。

后端 Java 也可以调取存储的压缩结果进行解压,重新发往前端

这里介绍 pako.js 的zlib 接口 与 Java 的互通。

首先是前端:

由于 pako.js 库的压缩后的结果 是 Uint8Array

Uint8Array 数组类型表示一个8位无符号整型数组,创建时内容被初始化为0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。

由于 它的 toString() 不包含特殊字符,故可以被 http 直接传输 (无需 转换为 base64)。

故发送到服务端的串 ,大致形式为 : 123,12,99,1,34

然后是 Java 的服务端

Java 原生支持 zlib 压缩和解压方式,百度上很多例子。这里不赘述。

略微麻烦的地方在于,

接受端:前端发送过来的上述的那种格式,需要转变为 java 的压缩解压接口的参数的固定格式。

发送端:发送给前端的数据(显然是 zlib 压缩后的数据),同样需要转换为 上述格式。

这里强调下,为什么前端解压后端的压缩数据时,一定要让后端发送给前端的数据格式,去和前端库发送给后端的数据格式保持一致呢?(不要吐槽我的逗号断句,这句实在太绕了)

因为 在前后端分离的开发模式下,对于前端开发人员,是不应该关注后端的技术实现。显然,后端努力去迎合 前端库的特有数据格式(因伟大而落泪)。

下面直接贴上 代码:

前端代码:(用 jquery 库)

// 首先你需要引入 pako.js 库,这里就不贴了

// 这里要压缩的内容

let content = "我是张三 **@*¥)*¥*)@#*#*@+------ ~kdfkda55d4 fd";

// 前端压缩

let clientData = pako.deflate(content);

// 变成 串

clientData = clientData.toString()

console.log("client 压缩后>>",clientData)

$.post("http://localhost:10003/demo/test2CompresAndUncompress",{

data:clientData

},function(data){

console.log("接受 server 压缩原文:",data);

let b = data.split(',').map(function (x) { return parseInt(x); });

// console.log("client 解压后split:",b);

let c = pako.inflate(b,{to :"string"});

// 完毕 撒花

console.log("client 解压后:",c);

});

后端代码(这里用的是 springboot 框架):

Controller:

@RequestMapping(value = "/test2CompresAndUncompress")

@ResponseBody

public String test2CompresAndUncompress(@RequestParam String data) throws IOException {

System.out.println("接収 client 原文<<"+data);

/**

* 将数字的字符串 转为 byte[]

*/

byte[] clientBytes = PakoUtil.receive(data);

byte[] bytes = ZlibUtil.decompress(clientBytes);

System.out.println("server 解压后<<"+new String(bytes));

//重新压缩,打算向服务器 发送 压缩后的代码

byte[] encodingStr = ZlibUtil.compress(bytes);

System.out.println("我自己尝试解压后1>>"+new String(encodingStr));

System.out.println("我自己尝试解压后2>>"+new String(ZlibUtil.decompress(encodingStr)));

return PakoUtil.send(encodingStr);

}

上面代码涉及的工具类(ZlibUtil.java 和 PakoUtil.java):

ZlibUtil.java:

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.UnsupportedEncodingException;

import java.util.Arrays;

import java.util.zip.Deflater;

import java.util.zip.DeflaterOutputStream;

import java.util.zip.Inflater;

import java.util.zip.InflaterInputStream;

/**

* zlib 压缩算法

* java 就是牛,原生支持

* @author jx

*

*/

public class ZlibUtil {

/**

* 压缩

*

* @param data

* 待压缩数据

* @return byte[] 压缩后的数据

*/

public static byte[] compress(byte[] data) {

byte[] output = new byte[0];

Deflater compresser = new Deflater();

compresser.reset();

compresser.setInput(data);

compresser.finish();

ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);

try {

byte[] buf = new byte[1024];

while (!compresser.finished()) {

int i = compresser.deflate(buf);

bos.write(buf, 0, i);

}

output = bos.toByteArray();

} catch (Exception e) {

output = data;

e.printStackTrace();

} finally {

try {

bos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

compresser.end();

return output;

}

/**

* 压缩

*

* @param data

* 待压缩数据

*

* @param os

* 输出流

*/

public static void compress(byte[] data, OutputStream os) {

DeflaterOutputStream dos = new DeflaterOutputStream(os);

try {

dos.write(data, 0, data.length);

dos.finish();

dos.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 解压缩

*

* @param data

* 待压缩的数据

* @return byte[] 解压缩后的数据

*/

public static byte[] decompress(byte[] data) {

byte[] output = new byte[0];

Inflater decompresser = new Inflater();

decompresser.reset();

decompresser.setInput(data);

ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);

try {

byte[] buf = new byte[1024];

while (!decompresser.finished()) {

int i = decompresser.inflate(buf);

o.write(buf, 0, i);

}

output = o.toByteArray();

} catch (Exception e) {

output = data;

e.printStackTrace();

} finally {

try {

o.close();

} catch (IOException e) {

e.printStackTrace();

}

}

decompresser.end();

return output;

}

/**

* 解压缩

*

* @param is

* 输入流

* @return byte[] 解压缩后的数据

*/

public static byte[] decompress(InputStream is) {

InflaterInputStream iis = new InflaterInputStream(is);

ByteArrayOutputStream o = new ByteArrayOutputStream(1024);

try {

int i = 1024;

byte[] buf = new byte[i];

while ((i = iis.read(buf, 0, i)) > 0) {

o.write(buf, 0, i);

}

} catch (IOException e) {

e.printStackTrace();

}

return o.toByteArray();

}

public static void main(String[] args) throws UnsupportedEncodingException {

String data = "aadfklafdafla我是中国人的啦啦啦";

System.out.println("原文:"+data);

// 报错

// String a = Base64Util.encode(ZlibUtil.compress(data.getBytes()));

//

// String b = new String(ZlibUtil.decompress(Base64Util.decode(a)));

byte[] a = ZlibUtil.compress(data.getBytes("UTF-8"));

System.out.println(">>"+Arrays.toString(a));

byte[] b = ZlibUtil.decompress(a);

// System.out.println("压缩后:"+a);

System.out.println("jieya后:"+new String(b));

}

void a(){

// try {

// // Encode a String into bytes

// String inputString = "Pehla nasha Pehla khumaar Naya pyaar hai naya intezaar Kar loon main kya apna haal Aye dil-e-bekaraar Mere dil-e-bekaraar Tu hi bata Pehla nasha Pehla khumaar Udta hi firoon in hawaon mein kahin Ya main jhool jaoon in ghataon mein kahin Udta hi firoon in hawaon mein kahin Ya main jhool jaoon in ghataon mein kahin Ek kar doon aasmaan zameen Kaho yaaron kya karoon kya nahin Pehla nasha Pehla khumaar Naya pyaar hai naya intezaar Kar loon main kya apna haal Aye dil-e-bekaraar Mere dil-e-bekaraar Tu hi bata Pehla nasha Pehla khumaar Usne baat ki kuchh aise dhang se Sapne de gaya vo hazaaron range ke Usne baat ki kuchh aise dhang se Sapne de gaya vo hazaaron range ke Reh jaoon jaise main haar ke Aur choome vo mujhe pyaar se Pehla nasha Pehla khumaar Naya pyaar hai naya intezaar Kar loon main kya apna haal Aye dil-e-bekaraar Mere dil-e-bekaraar";

// byte[] input = inputString.getBytes("UTF-8");

// // Compress the bytes

// byte[] output1 = new byte[input.length];

// Deflater compresser = new Deflater();

// compresser.setInput(input);

// compresser.finish();

// int compressedDataLength = compresser.deflate(output1);

// compresser.end();

// String str = Base64.encode(output1);

// System.out.println("Deflated String:" + str);

// byte[] output2 = Base64.decode(str);

// // Decompress the bytes

// Inflater decompresser = new Inflater();

// decompresser.setInput(output2);

// byte[] result = str.getBytes();

// int resultLength = decompresser.inflate(result);

// decompresser.end();

// // Decode the bytes into a String

// String outputString = new String(result, 0, resultLength, "UTF-8");

// System.out.println("Deflated String:" + outputString);

// } catch (UnsupportedEncodingException e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// } catch (DataFormatException e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }

//

}

}

PakoUtil.java:

/**

* 针对 前端的 pako.js 压缩和解压插件 的发送、推送的数据处理

* 目标是使和Java 的zlib 压缩解压交互方便

* @see http://nodeca.github.io/pako/#inflate

* @author jx

*

*/

public class PakoUtil {

/**

* 从 Pako.js 中接受的数据

* @param arrStr 形如: 123,2,09,

* 字符串是由无符号整数构成,逗号分隔

* @return

*/

public static byte[] receive(String arrInt){

/**

* 将数字字符串 -> byte[]

*/

String[] a = arrInt.split(",");

byte[] clientBytes = new byte[a.length];

int i = 0;

for (String e : a) {

clientBytes[i] = Integer.valueOf(e).byteValue();

i++;

}

return clientBytes;

}

/**

* 发送给 Pako 的数据格式

* @param bytes 服务端生成的字节数组

* @return String 发送给 pako.js 的数据格式

*/

public static String send(byte[] bytes) {

String[] ints = new String[bytes.length];

int j=0;

for(byte e:bytes) {

int t = e;

if(t<0) {

t = 256+t;

}

ints[j++] = String.valueOf(t);

}

return String.join(",", ints);

}

}

原文链接:https://blog.csdn.net/rainyspring4540/article/details/121383490

相关推荐
HaiFan.25 分钟前
SpringBoot 事务
java·数据库·spring boot·sql·mysql
2401_8827275731 分钟前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
我要学编程(ಥ_ಥ)34 分钟前
一文详解“二叉树中的深搜“在算法中的应用
java·数据结构·算法·leetcode·深度优先
NoneCoder34 分钟前
CSS系列(36)-- Containment详解
前端·css
music0ant36 分钟前
Idea 添加tomcat 并发布到tomcat
java·tomcat·intellij-idea
anyup_前端梦工厂1 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand1 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
计算机徐师兄1 小时前
Java基于SSM框架的无中介租房系统小程序【附源码、文档】
java·微信小程序·小程序·无中介租房系统小程序·java无中介租房系统小程序·无中介租房微信小程序
源码哥_博纳软云1 小时前
JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
GDAL1 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js