当前位置:首页 » 《关于电脑》 » 正文

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

16 人参与  2024年12月10日 18:01  分类 : 《关于电脑》  评论

点击全文阅读


工具介绍:
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


点击全文阅读


本文链接:http://zhangshiyu.com/post/199246.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1