web-dev-qa-db-fra.com

Décompressez la chaîne gzip et zlib en javascript

Je veux obtenir des données de couche de compression à partir du fichier tmx. Qui connaît les bibliothèques pour décompresser les chaînes gzip et zlib en javascript? J'essaye zlib mais ça ne marche pas pour moi. Par exemple, les données de couche dans le fichier tmx sont:

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

Mon code javascript est

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

Il s'exécute avec le message d'erreur "Méthode de compression non prise en charge". Mais j'essaie de décompresser avec l'outil en ligne comme http://i-tools.org/gzip , il retourne une chaîne correcte.

21
Toan Nguyen

Je peux résoudre mon problème en zlib . Je fixe mon code comme ci-dessous

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();
9
Toan Nguyen

Pako est un port Zlib complet et moderne.

Voici un exemple très simple et vous pouvez travailler à partir de là.

Obtenez pako.js et vous pouvez décompresser byteArray comme ceci:

<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>

Exemple d'exécution: http://jsfiddle.net/9yH7M/

Alternativement, vous pouvez coder en base64 le tableau avant de l'envoyer car le tableau prend beaucoup de temps lors de l'envoi en JSON ou XML. Décode également:

// 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);

Exemple d'exécution: http://jsfiddle.net/9yH7M/1/

Pour aller plus loin, voici la documentation de l'API pako .

26
Redsandro

Pour toute personne utilisant Ruby on Rails, qui souhaite envoyer des données encodées compressées au navigateur, puis les décompresser via Javascript sur le navigateur, j'ai combiné les deux excellentes réponses ci-dessus dans la solution suivante. Voici le code du serveur Rails dans mon contrôleur d'application qui compresse et code une chaîne avant de l'envoyer au navigateur via une variable @ dans un fichier . html.erb :

require 'zlib'
require 'base64'

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

Voici la fonction Javascript, qui utilise 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));
}

Voici un appel javascript à cette fonction de décompression, qui veut décoder et décompresser les données stockées dans un champ HTML caché:

my_answer = uncompress('my_hidden_field');

Voici l'entrée du fichier Rails application.js pour appeler pako. min.js , qui se trouve dans le répertoire /vendor/assets/javascripts :

//= require pako.min

Et j'ai obtenu le fichier pako.min.js à partir d'ici:

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

Tout fonctionne de mon côté, en tout cas! :-)

4
Andy Duncan