Implementazione JavaScript di Gzip [chiuso]


208

Sto scrivendo un'applicazione Web che deve archiviare i dati JSON in una piccola cache lato server di dimensioni fisse tramite AJAX (pensate a: quote quote aperte ). Non ho il controllo sul server.

Ho bisogno di ridurre la dimensione dei dati memorizzati per rimanere all'interno di una quota lato server e speravo di essere in grado di decomprimere il JSON con stringhe nel browser prima di inviarlo al server.

Tuttavia, non riesco a trovare molto in termini di implementazioni JavaScript di Gzip. Qualche suggerimento su come posso comprimere i dati sul lato client prima di inviarli?


6
Stai inviando esso fino al server. Ecco perché ci sono le nozioni di "upload" e "download". Forse è per questo che stai ricevendo risposte che ti dicono "il server può farlo".
Tomalak,

3
Una corretta implementazione di questo è probabilmente complicata, dal momento che JavaScript è a thread singolo. Probabilmente dovrebbe comprimersi in batch, usando setTimeout (), in modo che l'interfaccia utente non si blocchi durante la compressione.
August Lilleaas,

forse potresti scrivere il tuo algoritmo di compressione
Captain kurO,

3
@AugustLilleaas ora puoi usare i webworker per farlo :)
Capitano Ovvio,

Risposte:


138

Modifica Sembra esserci una soluzione LZW migliore che gestisce correttamente le stringhe Unicode su http://pieroxy.net/blog/pages/lz-string/index.html (Grazie a pieroxy nei commenti).


Non conosco implementazioni di gzip, ma la libreria jsolait (il sito sembra essere andato via) ha funzioni per la compressione / decompressione di LZW. Il codice è coperto dalla LGPL .

// LZW-compress a string
function lzw_encode(s) {
    var dict = {};
    var data = (s + "").split("");
    var out = [];
    var currChar;
    var phrase = data[0];
    var code = 256;
    for (var i=1; i<data.length; i++) {
        currChar=data[i];
        if (dict[phrase + currChar] != null) {
            phrase += currChar;
        }
        else {
            out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
            dict[phrase + currChar] = code;
            code++;
            phrase=currChar;
        }
    }
    out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
    for (var i=0; i<out.length; i++) {
        out[i] = String.fromCharCode(out[i]);
    }
    return out.join("");
}

// Decompress an LZW-encoded string
function lzw_decode(s) {
    var dict = {};
    var data = (s + "").split("");
    var currChar = data[0];
    var oldPhrase = currChar;
    var out = [currChar];
    var code = 256;
    var phrase;
    for (var i=1; i<data.length; i++) {
        var currCode = data[i].charCodeAt(0);
        if (currCode < 256) {
            phrase = data[i];
        }
        else {
           phrase = dict[currCode] ? dict[currCode] : (oldPhrase + currChar);
        }
        out.push(phrase);
        currChar = phrase.charAt(0);
        dict[code] = oldPhrase + currChar;
        code++;
        oldPhrase = phrase;
    }
    return out.join("");
}

11
Secondo Wikipedia, i brevetti sono scaduti alcuni anni fa. Potrebbe essere una buona idea verificarlo però.
Matthew Crumley,

3
LZW è troppo vecchio per essere ancora brevettato. Gli ultimi brevetti sono scaduti nel 2003 o giù di lì. Ci sono molte implementazioni gratuite.
ypnos,

5
Vedo almeno due problemi con il codice sopra: 1) prova a comprimere "Prova a comprimere questo \ u0110 \ u0111 \ u0112 \ u0113 \ u0114 caratteri non ascii.", 2) Non viene segnalato alcun errore se il codice> 65535.
Alcuni

5
Qui ci sono implementazioni in 21 lingue diverse rosettacode.org/wiki/LZW_compression è scritto che è di dominio pubblico dal 2004.
jcubic,

5
@some Ho appena rilasciato una piccola lib correggendo esattamente i problemi che stai segnalando qui: pieroxy.net/blog/pages/lz-string/index.html
pieroxy

53

Ho avuto un altro problema, non volevo codificare i dati in gzip ma decodificare i dati gzip . Sto eseguendo il codice javascript al di fuori del browser, quindi ho bisogno di decodificarlo utilizzando javascript puro .

Mi ci è voluto del tempo ma ho scoperto che nella libreria JSXGraph esiste un modo per leggere i dati compressi con gzip.

Qui è dove ho trovato la libreria: http://jsxgraph.uni-bayreuth.de/wp/2009/09/29/jsxcompressor-zlib-compressed-javascript-code/ Esiste anche un'utilità autonoma che può farlo, JSXCompressor e il codice è certificato LGPL.

Includi semplicemente il file jsxcompressor.js nel tuo progetto e sarai in grado di leggere i dati gzip codificati in base 64:

<!doctype html>
</head>
<title>Test gzip decompression page</title>
<script src="jsxcompressor.js"></script>
</head>
<body>
<script>
    document.write(JXG.decompress('<?php 
        echo base64_encode(gzencode("Try not. Do, or do not. There is no try.")); 
    ?>'));
</script>
</html>

Capisco che non è quello che volevi, ma rispondo ancora qui perché sospetto che possa aiutare alcune persone.


3
Grazie mille per la condivisione ancora. Questo è esattamente ciò di cui avevo bisogno. Probabilmente mi hai risparmiato ore di ricerche infruttuose che davvero non posso risparmiare. +1
Kiruse,

1
Mi chiedo perché mai si chiama "compressore" quando è un compressore UN. lol
matteo

1
quasi 5 anni dopo, ancora utile. grazie. Sto scaricando un grande JSON direttamente sulla pagina, invece di AJAX. pre-comprimendolo con PHP e decomprimendolo nuovamente nel lato client di JavaScript: sto risparmiando un po 'dell'overhead.

Abbiamo bisogno del <?php..bit? ... chiedo perché è passato al decompressmetodo.
Jus12

ricevo14:16:28.512 TypeError: e.replace is not a function[Weitere Informationen] jsxcompressor.min.js:19:12201
Bluscream il

40

Abbiamo appena rilasciato pako https://github.com/nodeca/pako , porta da zlib a javascript. Penso che sia l'implementazione js più veloce di deflate / inflate / gzip / ungzip. Inoltre, ha la licenza democratica del MIT. Pako supporta tutte le opzioni di zlib e i suoi risultati sono binari uguali.

Esempio:

var inflate = require('pako/lib/inflate').inflate; 
var text = inflate(zipped, {to: 'string'});

7
Fornisci un esempio sul lato client per la decodifica delle stringhe gzip.
Redsandro,

2
var inflate = require('pako/lib/inflate').inflate; var text = inflate(zipped, {to: 'string'});@Redsandro ecco come uso pako.
forresto,

Questo esempio da parte dei clienti generaincorrect header check
duhaime,


14

Ecco alcuni altri algoritmi di compressione implementati in Javascript:


questa implementazione di LZMA richiede BrowserPlus (un'estensione del browser) e non sembra essere Javascript puro
Piotr Findeisen,

questa implementazione di LZ77 non è più disponibile e almeno la sua versione di Python (pubblicata sulla stessa pagina) era errata per input abbastanza semplici.
Piotr Findeisen,

Geocities morto, aggiornerà il collegamento
Mauricio Scheffer,

Questo è abbastanza vicino a quello che voglio. anche le cose su Google verranno aggiornate qui
Theofanis Pantelides


0

Immagino che un'implementazione di compressione JavaScript generica sul lato client sarebbe un'operazione molto costosa in termini di tempo di elaborazione rispetto al tempo di trasferimento di alcuni altri pacchetti HTTP con payload non compresso.

Hai fatto qualche test che ti avrebbe dato un'idea di quanto tempo c'è da risparmiare? Voglio dire, il risparmio di larghezza di banda non può essere quello che stai cercando, o può?


Devo mantenere la dimensione totale dei dati entro una determinata quota: la dimensione è più importante del tempo.
David Citron,

Hm ... Perché il limite? Solo curioso.
Tomalak,

Bene, ecco il punto di vista di Google: code.google.com/apis/opensocial/articles/… - Le quote tipiche di Opensocial sono circa 10K.
David Citron,

Vedo, grazie per il chiarimento.
Tomalak,

1
A seconda dell'intensità della compressione, è possibile utilizzare gli operatori Web per eseguire l'attività dietro le quinte.
Zachleat,

-3

La maggior parte dei browser può decomprimere gzip al volo. Potrebbe essere un'opzione migliore di un'implementazione javascript.


20
Sì, ma devo comprimere i dati sul lato client prima di inviarli in giù ...
David Citron

-4

È possibile utilizzare un'applet Java da 1 pixel per 1 pixel incorporata nella pagina e utilizzarla per la compressione.

Non è JavaScript e i client avranno bisogno di un runtime Java ma farà ciò di cui hai bisogno.


7
Interessante, ma preferirei evitare di includere un'applet, se possibile.
David Citron,

Vorrei aggiungere i casi d'uso reali
cmc

1
Non è una buona soluzione in quanto aggiunge una dipendenza a Java. A parte questo, non tutti si sono preoccupati di installare java - il sito non funzionerà per alcune persone. Personalmente ho installato Java poiché ne avevo bisogno per qualcosa molto tempo fa, ma preferisco visitare siti che non usano Java.
Onkelborg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.