JavaScript-Implementierung von Gzip [geschlossen]

208

Ich schreibe eine Webanwendung, die JSON-Daten über AJAX in einem kleinen serverseitigen Cache mit fester Größe speichern muss (siehe: Offensoziale Kontingente ). Ich habe keine Kontrolle über den Server.

Ich muss die Größe der gespeicherten Daten reduzieren, um innerhalb eines serverseitigen Kontingents zu bleiben, und hatte gehofft, den stringierten JSON im Browser zu komprimieren, bevor ich ihn an den Server sende.

Allerdings kann ich bei JavaScript-Implementierungen von Gzip nicht viel finden. Irgendwelche Vorschläge, wie ich die Daten auf der Clientseite komprimieren kann, bevor ich sie sende?

David Citron
quelle
6
Sie senden es bis zum Server. Deshalb gibt es die Begriffe "Upload" und "Download". Vielleicht erhalten Sie deshalb Antworten, die Ihnen sagen, dass "der Server das kann".
Tomalak
3
Eine ordnungsgemäße Implementierung ist wahrscheinlich schwierig, da Javascript Single-Threaded ist. Es müsste wahrscheinlich mit setTimeout () stapelweise komprimiert werden, damit die Benutzeroberfläche beim Komprimieren nicht blockiert.
August Lilleaas
Vielleicht könnten Sie Ihren eigenen Komprimierungsalgorithmus schreiben
Captain KurO
3
@ AugustLilleaas jetzt können Sie Webworker verwenden, um dies zu tun :)
Captain Obvious

Antworten:

138

Bearbeiten Es scheint eine bessere LZW-Lösung zu geben, die Unicode-Zeichenfolgen unter http://pieroxy.net/blog/pages/lz-string/index.html korrekt verarbeitet (Dank an Pieroxy in den Kommentaren).


Ich kenne keine gzip-Implementierungen, aber die jsolait-Bibliothek (die Site scheint verschwunden zu sein) verfügt über Funktionen für die LZW-Komprimierung / -Dekomprimierung. Der Code wird von der LGPL abgedeckt .

// 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("");
}
Matthew Crumley
quelle
11
Laut Wikipedia sind die Patente vor einigen Jahren abgelaufen. Es könnte jedoch eine gute Idee sein, dies zu überprüfen.
Matthew Crumley
3
Das LZW ist viel zu alt, um noch patentiert zu werden. Die letzten Patente liefen ungefähr 2003 aus. Es gibt viele kostenlose Implementierungen.
Ypnos
5
Ich sehe mindestens zwei Probleme mit dem obigen Code: 1) Versuchen Sie zu komprimieren "Test zum Komprimieren dieser \ u0110 \ u0111 \ u0112 \ u0113 \ u0114 Nicht-ASCII-Zeichen.", 2) Bei Code> 65535 wird kein Fehler gemeldet.
Einige
5
Hier sind Implementierungen in 21 verschiedenen Sprachen. Rosettacode.org/wiki/LZW_compression Es wurde geschrieben, dass es ab 2004 gemeinfrei ist.
jcubic
5
@some Ich habe gerade eine kleine Bibliothek veröffentlicht, die genau die Probleme korrigiert, auf die Sie hier hinweisen: pieroxy.net/blog/pages/lz-string/index.html
pieroxy
53

Ich hatte ein anderes Problem, ich wollte keine Daten in gzip codieren, sondern gzipped Daten decodieren . Ich führe Javascript-Code außerhalb des Browsers aus, daher muss ich ihn mit reinem Javascript dekodieren .

Es hat einige Zeit gedauert, aber ich habe das im JSXGraph gefunden Bibliothek eine Möglichkeit gibt, komprimierte Daten zu lesen.

Hier habe ich die Bibliothek gefunden: http://jsxgraph.uni-bayreuth.de/wp/2009/09/29/jsxcompressor-zlib-compressed-javascript-code/ Es gibt sogar ein eigenständiges Dienstprogramm, das das kann, JSXCompressor und der Code ist LGPL-lizenziert.

Fügen Sie einfach die Datei jsxcompressor.js in Ihr Projekt ein, und Sie können dann eine Basis 64-codierte komprimierte Daten lesen:

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

Ich verstehe, dass es nicht das ist, was Sie wollten, aber ich antworte hier immer noch, weil ich vermute, dass es einigen Menschen helfen wird.

pcans
quelle
3
Vielen Dank für das weitere Teilen. Genau das brauchte ich. Sie haben mir wahrscheinlich Stunden erfolgloser Suche erspart, die ich wirklich nicht verschonen kann. +1
Kiruse
1
Ich frage mich, warum um alles in der Welt es "Kompressor" genannt wird, wenn es ein UN-Kompressor ist. lol
matteo
1
fast 5 Jahre später immer noch nützlich. Danke. Ich speichere einen großen JSON direkt auf der Seite, anstatt ihn mit AJAX zu versehen. Durch Vorkomprimieren mit PHP und Zurückkomprimieren auf der JavaScript-Clientseite spare ich einen Teil des Overheads.
Brauchen wir das <?php..Bit? .. Ich frage, weil es an die decompressMethode übergeben wird.
Jus12
Ich bekomme14:16:28.512 TypeError: e.replace is not a function[Weitere Informationen] jsxcompressor.min.js:19:12201
Bluscream
40

Wir haben gerade pako https://github.com/nodeca/pako veröffentlicht , Port von zlib nach Javascript. Ich denke, das ist jetzt die schnellste js-Implementierung von deflate / inflate / gzip / ungzip. Außerdem hat es eine demokratische MIT-Lizenz. Pako unterstützt alle zlib-Optionen und die Ergebnisse sind binär gleich.

Beispiel:

var inflate = require('pako/lib/inflate').inflate; 
var text = inflate(zipped, {to: 'string'});
Vitaly
quelle
7
Bitte geben Sie ein clientseitiges Beispiel für die Dekodierung von komprimierten Zeichenfolgen an.
Redsandro
2
var inflate = require('pako/lib/inflate').inflate; var text = inflate(zipped, {to: 'string'});@ Redsandro hier ist, wie ich pako benutze.
Forresto
Das clientseitige Beispiel wirftincorrect header check
duhaime
17

Ich habe eine Implementierung von LZMA von einem GWT-Modul in eigenständiges JavaScript portiert. Es heißt LZMA-JS .


quelle
1
hast du ein kompatibles PHP Modul dafür?
Sirber
dass url ist 404, und ich kann es nicht finden github.com/nmrugg entweder
hanshenrik
Entschuldigung, der Link wurde geändert. Hier ist die neue: lzma-js.github.io/LZMA-JS
14

Hier sind einige andere in Javascript implementierte Komprimierungsalgorithmen:

Mauricio Scheffer
quelle
Diese LZMA-Implementierung erfordert BrowserPlus (eine Browser-Erweiterung) und scheint kein reines Javascript zu sein
Piotr Findeisen
Diese LZ77-Implementierung ist nicht mehr verfügbar und zumindest die Python-Version (auf derselben Seite veröffentlicht) war für recht einfache Eingaben falsch.
Piotr Findeisen
Geocities tot, wird den Link aktualisieren
Mauricio Scheffer
Das ist ziemlich nah an dem, was ich will. Auch das Googeln wird hier aktualisiert
Theofanis Pantelides
8

Ich habe nicht getestet, aber es gibt eine Javascript-Implementierung von ZIP namens JSZip:

http://jszip.stuartk.co.uk/

https://stuk.github.io/jszip/

Sirber
quelle
1
Das ist Reißverschluss, nicht GZIP, und es verwendet Pako unter der Haube. Der Unterschied besteht darin, dass zip Dateiinfo-Metadaten enthält.
Vitaly
0

Ich denke, eine generische clientseitige JavaScript-Komprimierungsimplementierung wäre eine sehr teure Operation in Bezug auf die Verarbeitungszeit im Gegensatz zur Übertragungszeit einiger weiterer HTTP-Pakete mit unkomprimierter Nutzlast.

Haben Sie Tests durchgeführt, die Ihnen eine Vorstellung davon geben, wie viel Zeit Sie sparen müssen? Ich meine, Bandbreiteneinsparungen können nicht das sein, wonach Sie suchen, oder?

Tomalak
quelle
Ich muss die Gesamtdatengröße innerhalb eines bestimmten Kontingents halten - Größe ist wichtiger als Zeit.
David Citron
Hm ... Warum ist das Limit? Nur neugierig.
Tomalak
Nun, hier ist Googles Meinung dazu: code.google.com/apis/opensocial/articles/… - Typische OpenSocial-Quoten liegen bei etwa 10.000 .
David Citron
Ich verstehe, danke für die Klarstellung.
Tomalak
1
Je nachdem, wie intensiv die Komprimierung ist, können Sie Web-Worker verwenden, um die Aufgabe hinter den Kulissen auszuführen.
Zachleat
-3

Die meisten Browser können gzip im laufenden Betrieb dekomprimieren. Dies ist möglicherweise eine bessere Option als eine Javascript-Implementierung.


quelle
20
Ja, aber ich muss die Daten auf der Clientseite komprimieren, bevor ich sie abschicke ...
David Citron
-4

Sie können ein in die Seite eingebettetes Java-Applet mit 1 Pixel pro 1 Pixel verwenden und dieses zur Komprimierung verwenden.

Es ist kein JavaScript und die Clients benötigen eine Java-Laufzeit, aber es wird das tun, was Sie brauchen.

Bogdan
quelle
7
Interessant, aber ich würde es lieber vermeiden, wenn möglich ein Applet einzuschließen.
David Citron
Ich möchte die realen Anwendungsfälle hinzufügen
cmc
1
Keine gute Lösung, da Java dadurch abhängig wird. Abgesehen davon hat sich nicht jeder die Mühe gemacht, Java zu installieren - die Site wird für einige Leute nicht funktionieren. Persönlich habe ich Java installiert, da ich es vor langer Zeit für etwas gebraucht habe, aber ich bevorzuge es, Websites zu besuchen, die kein Java verwenden.
Onkelborg