当前位置: 首页 > news >正文

前端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

相关文章:

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

工具介绍&#xff1a; pako.js 前端压缩解压的库&#xff08;包含 zlib 和gzip 两种实现&#xff0c;这里只介绍 zlib&#xff09; pako 2.0.4 API documentation Java8 原生支持 zlib 和 gzip 业务场景 因为数据太大&#xff0c;网络环境不可控。故前端需要将数据 A 先压缩…...

unity 打包出来的所有执行文件内容打包成一个exe程序

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用Enigma Virtual Box1.下载安装包&#xff08;根据需要32位还是64位。一般是64位&#xff09;2.改个语言&#xff0c;方便使用&#xff08;改了后重启才…...

华为管理变革之道:组织文化与活力

目录 企业文化是什么&#xff1f; 为什么活下去是华为的文化&#xff1f; 活下来&#xff0c;是华为公司的最低纲领&#xff0c;也是华为公司的最高纲领&#xff01; 资源终会枯竭&#xff0c;唯有文化才能生生不息 企业文化之一&#xff1a;以客户为中心 企业文化之二&a…...

仿闲鱼的二手交易小程序软件开发闲置物品回收平台系统源码

市场前景 闲置物品交易软件的市场前景广阔&#xff0c;主要基于以下几个方面的因素&#xff1a; 环保意识提升&#xff1a;随着人们环保意识的增强&#xff0c;越来越多的人开始关注资源的循环利用&#xff0c;闲置物品交易因此受到了广泛的关注。消费升级与时尚节奏加快&…...

PostgreSQL CRUD 操作指南

PostgreSQL CRUD 操作指南 连接数据库 -- 连接到特定数据库 psql -U postgres -d xianxia-- 列出所有数据库 \l-- 切换数据库 \c xianxia-- 列出所有表 \dt-- 查看表结构 \d table_name基本 CRUD 操作 CREATE&#xff08;创建&#xff09; -- 创建新表 CREATE TABLE users …...

4X4规模S盒分量布尔函数计算工具(附各大常见分组加密算法S盒查找表和其对应分量布尔函数截图)

文章结尾有S盒分量布尔函数计算工具下载地址 Serpent {0x3,0x8,0xF,0x1,0xA,0x6,0x5,0xB,0xE,0xD,0x4,0x2,0x7,0x0,0x9,0xC} LBlock {0xE,0x9,0xF,0x0,0xD,0x4,0xA,0xB,0x1,0x2,0x8,0x3,0x7,0x6,0xC,0x5} GOST {0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0…...

模拟——郑益慧_笔记1_绪论

B站视频链接 模电是数电的基础&#xff1b;参考书&#xff1a; 模拟电子技术基础&#xff08;第四版&#xff09;华成英、童诗白主编&#xff0c;高等教育出版社&#xff1b;电子技术基础 模拟部分 康华光主编&#xff0c;高等教育出版社&#xff1b; 电子技术的发展史 电子…...

金融租赁系统的发展与全球化战略实施探讨

内容概要 金融租赁系统的演变并非一帆风顺&#xff0c;像一场跌宕起伏的电影。首先&#xff0c;咱们得看看它的起源及现状。随着经济的快速发展&#xff0c;金融租赁逐渐作为一种灵活的融资手段崭露头角。在中国市场中&#xff0c;企业对设备和技术更新换代的需求日益迫切&…...

vue3入门教程:计算属性

计算属性的基本用法 计算属性是通过computed函数创建的&#xff0c;它接受一个getter函数作为参数&#xff0c;并返回一个只读的响应式ref对象。该ref对象通过.value属性暴露getter函数的返回值。 <template><div><p>原始数据: {{ count }}</p><p…...

Docker怎么关闭容器开机自启,批量好几个容器一起操作?

环境&#xff1a; WSL2 docker v25 问题描述&#xff1a; Docker怎么关闭容器开机自启&#xff0c;批量好几个容器一起操作&#xff1f; 解决方案&#xff1a; 在 Docker 中&#xff0c;您可以使用多种方法来关闭容器并配置它们是否在系统启动时自动启动。以下是具体步骤和…...

shell脚本(全)

shell脚本概述 第一个shell脚本 shell注释 shell变量 shell位置参数 shell字符串 shell内置命令 shell命令替换 输出 流程控制IF export命令 退出脚本 运行Shell脚本 实例导航 shell脚本概述 在说什么是shell脚本之前&#xff0c;先说说什么是shell。 从程序员的…...

华为手机建议使用adb卸载的app

按需求自行卸载 echo 卸载智慧搜索 adb shell pm uninstall -k --user 0 com.huawei.search echo 卸载智慧助手 adb shell pm uninstall -k --user 0 com.huawei.intelligent echo 卸载讯飞语音引擎 adb shell pm uninstall -k --user 0 com.iflytek.speechsuite echo 卸载快应…...

论文解读 | EMNLP2024 一种用于大语言模型版本更新的学习率路径切换训练范式

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 点击 阅读原文 观看作者讲解回放&#xff01; 作者简介 王志豪&#xff0c;厦门大学博士生 刘诗雨&#xff0c;厦门大学硕士生 内容简介 新数据的不断涌现使版本更新成为大型语言模型&#xff08;LLMs&#xff…...

Java基础(Json和Java对象)

定义好实体类 package com.pyb.pojo; ​ /*** version 1.0* Author 彭彦彬* Date 2024/12/24 20:47* 注释*/ public class Person {private String username;private String password; ​public Person() {} ​public Person(String username, String password) {this.username…...

Linux 中检查 Apache Web Server (httpd) 正常运行时间的 4 种方法

注&#xff1a;机翻&#xff0c;未校。 4 Ways To Check Uptime of Apache Web Server (httpd) on Linux November 28, 2019 by Magesh Maruthamuthu We all know about the purpose of uptime command in Linux. 我们都知道 Linux 中 uptime 命令的目的。 It is used to c…...

Linux驱动开发--字符设备驱动开发

一、概述 字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节 流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、 IIC、 SPI, LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。 Linux 应用程序对驱动程…...

MarkItDown的使用(将Word、Excel、PDF等转换为Markdown格式)

MarkItDown的使用&#xff08;将Word、Excel、PDF等转换为Markdown格式&#xff09; 本文目录&#xff1a; 零、时光宝盒&#x1f33b; 一、简介 二、安装 三、使用方法 3.1、使用命令行形式 3.2、用 Python 调用 四、总结 五、参考资料 零、时光宝盒&#x1f33b; &a…...

一文彻底拿捏DevEco Studio的使用小技巧

程序员Feri一名12年的程序员,做过开发带过团队创过业,擅长Java相关开发、鸿蒙开发、人工智能等,专注于程序员搞钱那点儿事,希望在搞钱的路上有你相伴&#xff01;君志所向,一往无前&#xff01; 0.安装DevEco Studio DevEco Studio面向HarmonyOS应用及元服务开发者提供的集成开…...

R9000P键盘失灵解决办法

问题描述 突然&#xff0c;就是很突然&#xff0c;我买的R9000P 2024不到三个月&#xff0c;键盘突然都不能用了&#xff0c;是所有键盘按键都无效的那种。&#xff08;可以使用外接键盘&#xff09; 解决办法 我本科室友说的好哈&#xff0c;全坏全没坏。 &#xff08;该解…...

【Linux之Shell脚本实战】编写简单计算器shell脚本

【Linux之Shell脚本实战】编写简单计算器shell脚本 一、Shell脚本介绍1.1 Shell脚本简介1.2 Shell脚本特点二、脚本要求三、检查本地环境3.1 本地环境规划3.2 检查本地系统3.3 检查系统内核版本四、编写脚本4.1 脚本内容4.2 脚本分析整体逻辑各功能实现使用方法4.3 执行效果五、…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...