Реалізація JavaScript у Gzip [закрито]


208

Я пишу веб-додаток, в якому потрібно зберігати дані JSON у невеликому кешованому сервері фіксованого розміру через AJAX (подумайте: Оперсоціальні квоти ). У мене немає контролю над сервером.

Мені потрібно зменшити розмір збережених даних, щоб вони залишалися в рамках квоти на стороні сервера, і сподівався отримати можливість отримати gfip JSON в браузері, перш ніж надсилати їх на сервер.

Однак я не можу знайти багато способів реалізації JavaScript Gzip. Будь-які пропозиції щодо того, як я можу стискати дані на стороні клієнта, перш ніж надсилати їх?


6
Ви відправляєте його на сервер. Ось чому існують поняття «завантажувати» та «завантажувати». Можливо, тому ви отримуєте відповіді, які говорять вам про те, що "сервер може це зробити".
Томалак

3
Належна реалізація цього, ймовірно, складна, оскільки javascript є однопотоковою. Ймовірно, доведеться стискати в партіях, використовуючи setTimeout (), щоб інтерфейс користувача не замикався під час стискання.
Серпень Ліллеас

можливо, ви могли написати власний алгоритм стиснення
Капітан kurO

3
@AugustLilleaas тепер ви можете використовувати веб-працівників для цього :)
Капітан Очевидний

Відповіді:


138

Редагування. Здається, є кращим рішенням LZW, яке правильно обробляє рядки Unicode на веб-сторінці http://pieroxy.net/blog/pages/lz-string/index.html (Завдяки pieroxy у коментарях).


Я не знаю жодних реалізацій gzip, але бібліотека jsolait (здається, сайт пішов) має функції для стиснення / декомпресії LZW. Код охоплюється 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
За даними Вікіпедії, термін дії патентів минув кілька років тому. Це може бути хорошою ідеєю, щоб перевірити це, хоча.
Меттью Крамлі

3
LZW занадто старий, щоб його ще запатентувати. Останні патенти вийшли у 2003 році. Є безліч безкоштовних реалізацій.
ypnos

5
Я бачу щонайменше дві проблеми з кодом вище: 1) спробуйте стиснути "Тест на стиснення цього \ u0110 \ u0111 \ u0112 \ u0113 \ u0114 символів, які не є ascii.", 2) Про помилку не повідомляється, якщо код> 65535.
деякі

5
Ось реалізація на 21 різних мовах rosettacode.org/wiki/LZW_compression написано, що це у відкритому доступі з 2004 року.
jcubic

5
@some Я щойно випустив невеличку конфігурацію, яка виправляє саме ті проблеми, які ви вказуєте тут: pieroxy.net/blog/pages/lz-string/index.html
pieroxy

53

У мене виникла ще одна проблема: я не хотів кодувати дані в gzip, а розшифровувати gzipped дані . Я використовую код JavaScript за межами браузера, тому мені потрібно розшифрувати його за допомогою чистого JavaScript.

Ми зайняли деякий час, але я виявив, що в бібліотеці JSXGraph є спосіб зчитувати gzipped дані.

Тут я знайшов бібліотеку: http://jsxgraph.uni-bayreuth.de/wp/2009/09/29/jsxcompressor-zlib-compression-javascript-code/ Існує навіть окрема утиліта, яка може це зробити, JSXCompressor , і код ліцензований LGPL.

Просто включіть у свій проект файл jsxcompressor.js, і тоді ви зможете прочитати базові 64 закодовані gzipped дані:

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

Я розумію, що це не те, чого ви хотіли, але все ж відповідаю тут, бо підозрюю, що це допоможе деяким людям.


3
Дякую за те, що все ще поділилися. Це саме те, що мені було потрібно. Ви, напевно, врятували мене години невдалого пошуку, якого я справді не можу шкодувати. +1
Кірусе

1
Цікаво, чому на землі його називають "компресором", коли він є компресором ООН. lol
matteo

1
майже через 5 років, як і раніше корисно. спасибі. Я скидаю великий JSON безпосередньо на сторінку, а не AJAX'ing. попередньо стиснувши його з PHP та розпакувавши його назад у клієнтській частині JavaScript - я економив частину накладних витрат.

Чи потрібен нам <?php..шматочок? .. Я запитую, бо це передано decompressметоду.
1616 року

я отримую14:16:28.512 TypeError: e.replace is not a function[Weitere Informationen] jsxcompressor.min.js:19:12201
Bluscream

40

Ми щойно випустили pako https://github.com/nodeca/pako , порт zlib до javascript. Я думаю, це зараз найшвидша реалізація js deflate / inflate / gzip / ungzip. Крім того, він має демократичну ліцензію MIT. Pako підтримує всі параметри zlib, і його результати є двійковими рівними.

Приклад:

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

7
Наведіть приклад на стороні клієнта для декодування gzipped рядків.
Редсандро

2
var inflate = require('pako/lib/inflate').inflate; var text = inflate(zipped, {to: 'string'});@Redsandro ось як я використовую pako.
forresto

Цей клієнтський приклад кидаєincorrect header check
duhaime

17

Я переніс реалізацію LZMA з модуля GWT в окремий JavaScript. Це називається LZMA-JS .


1
у вас є сумісний модуль php для нього?
Сірбер

що URL - адреса є 404, і я не можу знайти його на github.com/nmrugg або
hanshenrik

На жаль, посилання змінилось. Ось новий: lzma-js.github.io/LZMA-JS

14

Ось деякі інші алгоритми стиснення, реалізовані в Javascript:


ця реалізація LZMA вимагає BrowserPlus (розширення для браузера) і, здається, не є чистим Javascript
Piotr Findeisen

ця реалізація LZ77 більше недоступна, і принаймні, версія Python (опублікована на одній сторінці) була неправильною для досить простих вводів.
Пьотр Фіндейзен

геоградів загинули, оновлять посилання
Маурісіо Шеффер

Це досить близько до того, що я хочу. Тут також оновлять googling речі
Theofanis Pantelides


0

Я думаю, що загальна реалізація стиснення JavaScript на стороні клієнта була б дуже дорогою операцією з точки зору часу обробки, на відміну від часу передачі ще декількох пакетів HTTP з нестисненим корисним навантаженням.

Чи зробили ви тестування, яке б дало вам уявлення, скільки часу потрібно зберегти? Я маю на увазі, заощадження пропускної здатності не може бути тим, про що ви хочете, чи можна?


Мені потрібно зберегти загальний розмір даних у межах певної квоти - розмір важливіший за час.
Девід Цитрон

Гм ... Чому межа? Просто цікаво.
Томалак

Що ж, ось Google взяв на себе це: code.google.com/apis/opensocial/articles/… - Типові міжсоціальні квоти становлять близько 10 к.
Девід Цитрон

Бачу, дякую за роз’яснення.
Томалак

1
Залежно від того, наскільки інтенсивно стискається, ви можете використовувати веб-працівників для виконання завдання за кадром.
zachleat

-3

Більшість браузерів може декомпресувати gzip на льоту. Це може бути кращим варіантом, ніж реалізація javascript.


20
Так, але мені потрібно стиснути дані на стороні клієнта, перш ніж надсилати їх…
David Citron

-4

Ви можете використовувати вбудований на сторінку аплет Java на 1 піксель на 1 піксель і використовувати його для стиснення.

Це не JavaScript, і клієнтам потрібен час виконання Java, але він виконуватиме все, що вам потрібно.


7
Цікаво, але я краще уникати включення аплету, якщо можливо.
Девід Цитрон

Я хотів би додати справжні випадки використання
cmc

1
Не гарне рішення, оскільки воно додає залежність від Java. Крім того, не всі намагаються встановлювати Java - сайт не працює для деяких людей. Особисто я встановив Java, оскільки мені це було потрібно для чогось давно, але я вважаю за краще відвідувати сайти, які не використовують Java.
Онкельборг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.