Сжатие шестнадцатеричной строки с помощью GZIP в Интернете (Javascript) - PullRequest
1 голос
/ 17 февраля 2020

У меня есть текстовое поле, в котором введенное значение преобразуется в шестнадцатеричное и объединяется, как показано ниже:

4f43 5441 1d00 0000 2400 0000 0004 0000
0200 0000 0000 0000 0000 0000 0000 0000
0200 0000 0206 0073 6b79 626f 780e 0073
6b79 626f 7865 732f 7768 6974 6502 0800
6d61 7074 6974 6c65 1900 4f47 5a20 4564
6974 6f72 2066 6972 7374 2065 7665 7220
6d61 7003 6670 7300 0000 0000 0500 0200
0400 0300 0500 0700 0000 0044 0000 0044
0000 0044 0000 0000 0000 00ff 0000 0500
0000 0544 0000 0544 0000 0044 6e00 3200
0000 0000 0000 0200 0207 0007 0007 0001
0001 0001 0000 0202 0003 0004 0005 0006
0007 0000 0202 0003 0004 0005 0006 0007
0000 0202 0003 0004 0005 0006 0007 0000
0200 0000 0000 0007 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0100 0000
0000 0000 0000 0000 0000 0100 0000 0000
0000 0000 0000 0000

Моя цель - сжать это шестнадцатеричное значение с помощью gzip "online" (т.е. без командной строки zlib / nodejs) и сделать вывод доступным для загрузки с использованием BLOB-объекта.

Это моя попытка на данный момент использовать " PAKO ":

html

<script src="https://cdn.jsdelivr.net/pako/1.0.3/pako.min.js"></script>
<textarea id="input"></textarea>
<button onclick="toHex()">Convert to hex</button>
<a id="downloadbtn">Download as gzip</button>

javascript

var pako = window.pako;
function toHex(){
    input = document.getElementById("input").value;
    hexresult = input.split("").reduce((hex,c)=>hex+=c.charCodeAt(0).toString(16).padStart(2,"0"),"");

    gzipresult = pako.gzip(hexresult, { level: 6 });
    download(gzipresult);
}

function download(data){
    downloadbtn = document.getElementById("downloadbtn");
    var blob = new Blob([ data ], {type : "application/gzip",});

    if (window.navigator.msSaveBlob) {
        navigator.msSaveBlob(blob, "output.gz");
    } else {
        var csvUrl = URL.createObjectURL(blob);
        $('#downloadbtn').attr({
            'download': "output.gz",
            'href': csvUrl
        });
    };
}

Однако вывод, сгенерированный PAKO (gzip), не совпадает с выводом, сгенерированным zlib, они не совпадают ...

Есть ли способ сделать вывод обоих идентичным? или как правильно сжать шестнадцатеричную строку для gzip, используя JavaScript?

Обновление: @Blex упомянул об использовании Buffer.from, я думаю это это что-то родное для nodejs (и оно мне нужно в браузере), поэтому я попробовал этот автономный скрипт из этого репо , однако сгенерированный файл остается тем же (все еще отличается от zlib), но в любом случае, я ценю попытку помочь!

Сравнение

Ввод: "68656c6c6f20776f726c6421" (Привет, мир!)

Вывод zlib (командная строка mingw): 1f8b 0800 4767 4c5e 0003 cb48 cdc9 c957 28cf 2fca 4951 0400 6dc2 b403 0c00 0000

pako output: 1f8b 0800 0000 0000 0003 33b3 3033 354b 06c2 3423 0373 73b3 3473 2320 dbc4 c810 00b2 2eed 2a18 0000 00

1 Ответ

1 голос
/ 17 февраля 2020

Редактировать: После написания этого ответа слишком быстро, я заметил, что результаты не были абсолютно одинаковыми. Разница в один байт соответствует заголовку типа OS . zlib возвращает a, что представляет TOPS-20 , а Pako возвращает 3, что представляет Unix.

zlib возвращает буфер , и Пако возвращает массив Uint8Array. Чтобы получить буфер, вы можете сделать:

gzipresult = pako.gzip(hexresult, { level: 6 });
gzipbuffer = Buffer.from(gzipresult);

Это даст вам точный аналогичный вывод для zlib. Вот простой NodeJS скрипт для тестирования и сравнения обоих:

// Don't forget to `npm i -S pako`
const pako = require("pako");
const zlib = require("zlib");

const input = "Hello world!";
const hexStr = input.split("").reduce((hex,c)=>hex+=c.charCodeAt(0).toString(16).padStart(2,"0"),"");

zlib.gzip(hexStr, function(_, zlibResult) {
  const zlibHex = zlibResult.toString("hex");

  const pakoResult = pako.gzip(hexStr, { level: 6 });
  const pakoHex = Buffer.from(pakoResult).toString("hex");

  console.log("zlib", zlibHex);
  console.log("pako", pakoHex);
  console.log("Outputs are equal ===", zlibHex === pakoHex);
});


/*
Output:
pako 1f8b080000000000000333b13033354b06c23423037373b334732320dbc4c81000bde2d6f318000000
zlib 1f8b080000000000000a33b13033354b06c23423037373b334732320dbc4c81000bde2d6f318000000
                        ^
             actually not the same
Outputs are equal === false
*/
...