Распакуйте gzip и строку zlib в JavaScript

Я хочу получить данные слоя сжатия из файла TMX. Кто знает библиотеки для распаковки gzip и zlib строки в javascript? Я пытаюсь zlib, но у меня это не работает. Например, данные слоя в файле tmx:

  <data encoding="base64" compression="zlib">
       eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==
  </data>

Мой код JavaScript

var base64Data = "eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==";
var compressData = atob(base64Data);
var inflate = new Zlib.Inflate(compressData);
var output = inflate.decompress();

Он работает с отображением сообщения об ошибке "неподдерживаемый метод сжатия" . Но я пытаюсь распаковать с онлайн-инструментом, как http://i-tools.org/gzip, он возвращает правильную строку.

4 ответа

Решение

Я могу решить мою проблему с помощью zlib. Я исправляю свой код, как показано ниже

var base64Data = "eJztwTEBAAAAwqD1T20JT6AAAHgaCWAAAQ==";
var compressData = atob(base64Data);
var compressData = compressData.split('').map(function(e) {
    return e.charCodeAt(0);
});
var inflate = new Zlib.Inflate(compressData);
var output = inflate.decompress();

Пако полный и современный Zlib порт.

Вот очень простой пример, и вы можете работать оттуда.

Получите pako.js, и вы можете распаковать byteArray следующим образом:

<html>
<head>
  <title>Gunzipping binary gzipped string</title>
  <script type="text/javascript" src="pako.js"></script>
  <script type="text/javascript">

    // Get datastream as Array, for example:
    var charData    = [31,139,8,0,0,0,0,0,0,3,5,193,219,13,0,16,16,4,192,86,214,151,102,52,33,110,35,66,108,226,60,218,55,147,164,238,24,173,19,143,241,18,85,27,58,203,57,46,29,25,198,34,163,193,247,106,179,134,15,50,167,173,148,48,0,0,0];

    // Turn number array into byte-array
    var binData     = new Uint8Array(charData);

    // Pako magic
    var data        = pako.inflate(binData);

    // Convert gunzipped byteArray back to ascii string:
    var strData     = String.fromCharCode.apply(null, new Uint16Array(data));

    // Output to console
    console.log(strData);

  </script>
</head>
<body>
    Open up the developer console.
</body>
</html>

Работающий пример: http://jsfiddle.net/9yH7M/

В качестве альтернативы вы можете кодировать массив с помощью base64, прежде чем отправлять его, так как Array занимает много времени при отправке в формате JSON или XML. Расшифровать аналогично:

// Get some base64 encoded binary data from the server. Imagine we got this:
var b64Data     = 'H4sIAAAAAAAAAwXB2w0AEBAEwFbWl2Y0IW4jQmziPNo3k6TuGK0Tj/ESVRs6yzkuHRnGIqPB92qzhg8yp62UMAAAAA==';

// Decode base64 (convert ascii to binary)
var strData     = atob(b64Data);

// Convert binary string to character-number array
var charData    = strData.split('').map(function(x){return x.charCodeAt(0);});

// Turn number array into byte-array
var binData     = new Uint8Array(charData);

// Pako magic
var data        = pako.inflate(binData);

// Convert gunzipped byteArray back to ascii string:
var strData     = String.fromCharCode.apply(null, new Uint16Array(data));

// Output to console
console.log(strData);

Работающий пример: http://jsfiddle.net/9yH7M/1/

Чтобы пойти более продвинутым, вот pako API документация.

Для тех, кто использует Ruby on Rails, кто хочет отправлять сжатые закодированные данные в браузер, а затем распаковывать их через Javascript в браузере, я объединил оба превосходных ответа выше в следующее решение. Вот код сервера Rails в моем контроллере приложения, который сжимает и кодирует строку перед отправкой в ​​браузер через @variable в файл .html.erb:

require 'zlib'
require 'base64'

    def compressor (some_string)
        Base64.encode64(Zlib::Deflate.deflate(some_string))
    end

Вот функция Javascript, которая использует pako.min.js:

function uncompress(input_field){
    base64data = document.getElementById(input_field).innerText;
    compressData = atob(base64data);
    compressData = compressData.split('').map(function(e) {
        return e.charCodeAt(0);
    });
    binData = new Uint8Array(compressData);
    data = pako.inflate(binData);
    return String.fromCharCode.apply(null, new Uint16Array(data));
}

Вот вызов javascript для этой функции распаковки, которая хочет распаковать и распаковать данные, хранящиеся в скрытом поле HTML:

my_answer = uncompress('my_hidden_field');

Вот запись в файле Rails application.js для вызова pako.min.js, которая находится в каталоге /vendor/assets/javascripts:

//= require pako.min

И я получил файл pako.min.js отсюда:

https://github.com/nodeca/pako/tree/master/dist

Все работает на моем конце, так или иначе!:-)

Я отправлял данные из скрипта Python и пытался декодировать их в JS. Вот что мне пришлось сделать:

Питон

      import base64
import json
import urllib.parse
import zlib

...

data_object = {
    '_id': '_id',
    ...
}
compressed_details = base64.b64encode(zlib.compress(bytes(json.dumps(data_object), 'utf-8'))).decode("ascii")
urlsafe_object = urllib.parse.quote(str(compressed_details))#.replace('%', '\%') # you likely don't need this last part
final_URL = f'https://my.domain.com?data_object={urlsafe_object}'

...

JS

      // npm install this
import pako from 'pako';

...

const urlParams = new URLSearchParams(window.location.search);
const data_object = urlParams.get('data_object');
if (data_object) {
    const compressedData = Uint8Array.from(window.atob(data_object), (c) => c.charCodeAt(0));
    originalObject = JSON.parse(pako.inflate(compressedData, { to: 'string' }));
};

...
Другие вопросы по тегам