如何在将客户端 JavaScript 中的数据发送到服务器之前对其进行压缩?
例如
可以使用什么样的压缩格式?
如今,网络浏览器在 JavaScript 中原生支持压缩。
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;
}