如何在网络浏览器中压缩二进制或文本数据,然后在服务器端用 JavaScript 对其进行解码?

问题描述 投票:0回答:1

如何在将客户端 JavaScript 中的数据发送到服务器之前对其进行压缩?

例如

  • 文字
  • JSON
  • 二进制数据

可以使用什么样的压缩格式?

javascript whatwg-streams-api
1个回答
0
投票

如今,网络浏览器在 JavaScript 中原生支持压缩。

  • 您可以使用常见的压缩方法(例如 Gzip)来压缩任何数据
  • 对于图像,您可以从画布中导出 PNG
  • Web 浏览器支持 Streams API 以及 CompressionStream
  • Node.js 内置了 zlib,提供了一些常见的压缩方法(尽管它的接口非常陈旧,需要针对异步进行调整)。
  • 在 Web 中,您可能需要对压缩的有效负载进行 Base64 编码和解码,因为将其嵌入到 JSON 等格式不支持二进制
  • 一个好的压缩格式是
    gzip
    ,因为它得到普遍支持

CompressionStream
仅支持 deflate (zip) 和 Gzip。

一个示例是如何在客户端 JavaScript 上压缩字符串(例如 JSON)。

示例

compress.js



/**
 * Compress strings and Blobs as gzip.
 * 
 * Based on https://dev.to/ternentdotdev/json-compression-in-the-browser-with-gzip-and-the-compression-streams-api-4135
 * 
 * @param {string | Blob} data Plain-text data as a string or Blob for binary data
 * 
 * @param {boolean} base64 Set true to output base64 encoded (can be embedded in JSON, query parameters, etc.), otherwise return JavaScript blob
 * 
 * @returns {Promise<string | Blob>} Compressed binary or
 */
export async function compressStringGzip(data, base64) {
    
    // Convert incoming string to a stream
    let stream;
    if(typeof data == "string") {
        stream = new Blob([data], {
            type: 'text/plain',
        }).stream();    
    } else {
        // Assume blog
        stream = data.stream();            
    }

    // gzip stream
    const compressedReadableStream = stream.pipeThrough(
        new CompressionStream("gzip")
    );
    
     // create Response
    const compressedResponse = await new Response(compressedReadableStream);

    // Get response Blob
    const blob = await compressedResponse.blob();

    if(base64) {
        // Get the ArrayBuffer
        const buffer = await blob.arrayBuffer();
        
        // convert ArrayBuffer to base64 encoded string
        const compressedBase64 = btoa(
          String.fromCharCode(
            ...new Uint8Array(buffer)
          )
        );        

        return compressedBase64;

    } else {
        return blob;
    }
}

decompress.js 示例:

import * as zlib from "zlib";
import * as util from "util";

/**
 * Decompress a string or a Buffer as gzip.
 * 
 * Assume the encoded data compresses as UTF-8 text.
 * 
 * Only for server-side Node.js.
 * 
 * @param {*} data Data to decompress, either Buffer or a string
 * 
 * @param {*} plainText Set true if the encoded data is utf-8 and you want to decode the stirng
 * 
 * @returns {Promise<string | Buffer>} Decompressed data as a Buffer object or a string if plainText is set
 */
export async function decompressStringGzip(data, plainText) {

    const gunzip = util.promisify(zlib.gunzip);

    // Assume base64 encoded if we are given data as a string
    if(typeof data == "string") {
        data = Buffer.from(data, 'base64');
    }

    const raw = await gunzip(data);

    if(plainText) {
        return raw.toString("utf-8");
    }
    
    return raw;
}


© www.soinside.com 2019 - 2024. All rights reserved.