【随手笔记】资料压缩

1,818 阅读2分钟

引言

在使用ws过程中,传输内容都是明文可见的,我希望用户看不到我们发送的内容,至少增加阅读成本,同时提高一下传输效率,所以在传输过程中我在出入口处添加了加压和解压的方法。

zlib

服务器我用的是node.js实现,node.js有自带的zlib库,所以我直接就用自带的了。我们先来看下zlib这模块,zlib有很多压缩方法:

详细文档

我们可以根据配置来选择需要的解压缩方法,首先我们先写两个方法,一个是压缩方法compress,一个是解压方法decompress

const zlib = require('zlib');

const compress = function(str, type) {
    switch (type) {
        case 'gzip':
            return zlib.gzipSync(str);
        case 'deflate':
            return zlib.deflateSync(str);
        case 'deflateRaw':
            return zlib.deflateRawSync(str);
        default:
            return str;
    }
}

const decompress = function(str, type) {
    switch (type) {
        case 'gzip':
            return zlib.gunzipSync(str).toString();
        case 'deflate':
            return zlib.inflateSync(str).toString();
        case 'deflateRaw':
            return zlib.inflateRawSync(str).toString();
        default:
            return str;
    }
}

我们只需要在send方法中使用compress压缩下内容:

const send = function (msg, id) {
    return new Promise((resolve, reject) => {
        try {
            const data = compress(JSON.stringify({id, msg}), 'deflateRaw');
            ... ...
        } catch (err) {
            reject(err);
        }
    });
}

在收到信息时候使用decompress解压下内容:

    socket.on('message', (_data) => {
        const data = decompress(_data, 'deflateRaw');
        if (typeOf data !== 'string') return;
        ... ...
    });

这样我们就完成了一个简单的服务器传输压缩功能。

pako

前端我选择用pako库来实现压缩资料的功能。一样实现两个方法compressdecompress。需要注意一下的是,Html5的websocket接收二进制数据格式有blobarraybuffer,默认是blob,我们可以通过websocket.binaryType来指定收到的二进制数据的格式。

详细文档

    import pako from 'pako';
    
    const compress = function (data, type) {
        switch (type) {
            case "gizp":
                return pako.gzip(data);
            case "deflate":
                return pako.deflate(data);
            case "deflateRaw":
                return pako.deflateRaw(data);
            default:
                return data;
        }
    }
    
    const decompress = async function (data, type) {
        if (data instanceof Blob) {
            data = await new Promise(resolve => {
                const reader = new FileReader();
                //byte为blob对象
                reader.readAsArrayBuffer(data);
                reader.onload = (e) => {
                    resolve(reader.result);
                }
            });
        }
        switch (type) {
            case "gizp":
                return pako.ungzip(data, { to: "string" });
            case "deflate":
                return pako.inflate(data, { to: "string" });
            case "deflateRaw":
                return pako.inflateRaw(data, { to: "string" });
            default:
                return data;
        }
    }

使用方法跟服务器的类似,就不详细说明了。最后我们在浏览器看下效果:

压缩后效果


END