Реалізація 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.