Реализация Gzip на JavaScript

Я пишу веб-приложение, которому необходимо хранить данные JSON в небольшом серверном кеше фиксированного размера через AJAX (подумайте: Opensocial квоты). Я не контролирую сервер.

Мне нужно уменьшить размер хранимых данных, чтобы оставаться в рамках квоты на стороне сервера, и я надеялся, что смогу сжать строковый JSON в браузере перед отправкой его на сервер.

Однако я не могу найти много способов реализации Gzip в JavaScript. Любые предложения о том, как я могу сжать данные на стороне клиента перед их отправкой?

Вы отправляете его вверх на сервер. Вот почему существуют понятия «загрузка» и «загрузка». Может быть, поэтому вы получаете ответы, в которых говорится, что «сервер может это сделать».

Tomalak 16.11.2008 23:27

Правильная реализация этого, вероятно, непростая, поскольку javascript является однопоточным. Вероятно, придется сжимать партиями, используя setTimeout (), чтобы пользовательский интерфейс не блокировался при сжатии.

August Lilleaas 15.09.2009 21:47

возможно, вы могли бы написать свой собственный алгоритм сжатия

Captain kurO 06.07.2012 07:43

@AugustLilleaas, теперь вы можете использовать для этого веб-воркеров :)

Captain Obvious 19.11.2014 13:24
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
210
4
167 023
9

Ответы 9

Большинство браузеров могут распаковывать gzip на лету. Это может быть лучшим вариантом, чем реализация javascript.

Да, но мне нужно сжать данные на стороне клиента перед их отправкой ...

David Citron 16.11.2008 23:07

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

Проводили ли вы какое-либо тестирование, которое дало бы вам представление о том, сколько времени нужно сэкономить? Я имею в виду, что экономия полосы пропускания не может быть тем, что вам нужно, или может?

Мне нужно сохранить общий размер данных в пределах определенной квоты - размер важнее времени.

David Citron 16.11.2008 23:45

Хм ... Почему предел? Просто любопытно.

Tomalak 16.11.2008 23:48

Что ж, вот взгляд Google на это: code.google.com/apis/opensocial/articles/… - Типичные квоты Opensocial составляют около 10 тысяч.

David Citron 16.11.2008 23:52

Понятно, спасибо за разъяснения.

Tomalak 16.11.2008 23:57

В зависимости от того, насколько интенсивно сжатие, вы можете использовать веб-воркеров для выполнения задачи «за кулисами».

zachleat 24.02.2010 16:33

Вы можете использовать Java-апплет 1 пиксель на 1 пиксель, встроенный в страницу, и использовать его для сжатия.

Это не JavaScript, и клиентам потребуется среда выполнения Java, но она сделает то, что вам нужно.

Интересно, но по возможности я бы предпочел не включать апплет.

David Citron 16.11.2008 23:53

Я хотел бы добавить реальные варианты использования

cmc 30.07.2012 20:00

Не лучшее решение, так как оно добавляет зависимость от Java. Кроме того, не все удосужились установить java - у некоторых сайт не будет работать. Лично у меня установлена ​​java, так как она мне была нужна давным-давно, но я предпочитаю посещать сайты, которые не используют java.

Onkelborg 11.02.2013 18:22

Редактировать Кажется, есть лучшее решение 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("");
}

Как может код быть LGPL, если алгоритм запатентован? Или срок действия всех патентов истек?

David Citron 17.11.2008 01:05

Согласно Википедии, срок действия патентов истек несколько лет назад. Хотя было бы неплохо проверить это.

Matthew Crumley 17.11.2008 01:39

LZW слишком стар, чтобы его все еще можно было запатентовать. Последние патенты истекли примерно в 2003 году. Есть множество бесплатных реализаций.

ypnos 17.11.2008 01:39

Я вижу по крайней мере две проблемы с приведенным выше кодом: 1) попробуйте сжать «Тест, чтобы сжать эти \ u0110 \ u0111 \ u0112 \ u0113 \ u0114 символы, отличные от ascii.», 2) Если код> 65535, об ошибке не сообщается.

some 17.11.2008 08:40

И я забыл о третьем: результат кодирования находится в UTF-16. Ваше приложение справляется с этим?

some 17.11.2008 08:47

Вот некоторая информация о том, как сжать Unicode: unicode.org/faq/compression.html. Похоже, это было не так уж и банально.

Tomalak 18.11.2008 10:07

В zapper.hodgers.com/files/javascript/lzw_test/lzw.js есть другая реализация LZW, я не знаю, решает ли это какую-либо из вышеперечисленных проблем. Также см. Соответствующую запись в блоге: zapper.hodgers.com/labs/?p=90

msanders 08.01.2009 14:27

FWIW - я не думаю, что реализация zapper.hodgers.com решает проблемы, описанные выше. Он отлично работал с «обычным старым ASCII», но когда я попробовал его на строке, сгенерированной, например, методом toDataUrl () холста HTML, сжатая, а затем распакованная строка не соответствовала оригиналу. Кто-нибудь реализовал сжатие JavaScript и декомпрессии таким образом, чтобы решить проблемы, указанные выше. и может справиться с производительностью со строками длиной примерно до 500 КБ - я понимаю, что это сложная задача!

Sam Dutton 05.08.2010 15:37

@Sam - попробуйте utf8_encode (lzw_encode (my_string)). Вот кодировщик UTF8 в Javascript: farhadi.ir/works/utf8.

Roy Tinker 27.10.2010 22:56

Вот реализации на 21 разных языках. rosettacode.org/wiki/LZW_compression написано, что он находится в общественном достоянии с 2004 года.

jcubic 21.02.2011 01:08

Кто-нибудь написал алгоритм сжатия, который еще нормально работает?

Olivier Lalonde 27.04.2013 06:50

Мне не удалось найти библиотеку jsolait по ссылке, могу ли я просто использовать код ответа в моем бесплатном приложении для веб-сайта?

simo 01.05.2013 07:37

@simo Похоже, что сайт отключили (по крайней мере, контент). Да, LGPL позволяет использовать код как есть в вашем приложении.

Matthew Crumley 01.05.2013 16:57

@some Я только что выпустил небольшую библиотеку, исправляющую именно те проблемы, которые вы здесь указываете: pieroxy.net/blog/pages/lz-string/index.html

pieroxy 09.05.2013 14:32

@pieroxy Спасибо, добавил ссылку на ваш сайт.

Matthew Crumley 09.05.2013 17:40

@ Мэтью Крамли, спасибо. Я использую библиотеку для самодельного RSS-ридера, и она кажется довольно стабильной. Я сжал (и успешно распаковал) несколько десятков мегабайт, и никаких проблем не возникло. Я уже подумываю добавить немного Хаффмана для правильного кодирования токенов, сгенерированных LZW, но мне нравится его скорость, поэтому я пока не знаю, куда я собираюсь пойти с этим.

pieroxy 13.05.2013 12:29

Красиво - jsfiddle.net/lordloh/uJj7d

Lord Loh. 28.02.2014 09:06

в моем тесте он работал некорректно - jsfiddle.net/4rh4js8h/1

hienbt88 17.04.2017 11:30

@ hienbt88 Похоже, вы столкнулись с проблемой Unicode со вторым знаком «-», который не является обычным дефисом. Я бы попробовал код Pieroxy, который должен уметь обрабатывать символы, отличные от ASCII.

Matthew Crumley 17.04.2017 17:09

Вот некоторые другие алгоритмы сжатия, реализованные в Javascript:

эта реализация LZMA требует BrowserPlus (расширение браузера) и не выглядит чистым Javascript

Piotr Findeisen 27.10.2009 11:36

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

Piotr Findeisen 30.10.2009 16:04

geocities мертв, обновлю ссылку

Mauricio Scheffer 30.10.2009 16:45

Это довольно близко к тому, что я хочу. гугл тоже обновится здесь

Theofanis Pantelides 02.03.2010 20:17

Я не тестировал, но есть реализация ZIP для javascript, которая называется JSZip:

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

Это zip, а не gzip, и он использует pako под капотом. Разница в том, что у zip есть метаданные информации о файле.

Vitaly 03.01.2016 03:03

Я перенес реализацию LZMA из модуля GWT в автономный JavaScript. Он называется LZMA-JS.

у вас есть совместимый модуль php для этого?

Sirber 07.09.2010 21:21

У меня была другая проблема, я хотел кодировать данные не в gzip, а в декодировать сжатые данные. Я запускаю код javascript вне браузера, поэтому мне нужно декодировать его с помощью javascript чистый.

Это заняло у меня некоторое время, но я обнаружил, что в библиотеке JSXGraph есть способ читать сжатые данные.

Вот где я нашел библиотеку: http://jsxgraph.uni-bayreuth.de/wp/2009/09/29/jsxcompressor-zlib-compressed-javascript-code/ Есть даже отдельная утилита, которая может это сделать, JSXCompressor, а код лицензирован LGPL.

Просто включите файл jsxcompressor.js в свой проект, и тогда вы сможете читать данные в формате gzip в кодировке 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>

Я понимаю, что это не то, что вы хотели, но я все равно отвечаю здесь, потому что подозреваю, что это поможет некоторым людям.

Большое спасибо за то, что все еще поделились. Это именно то, что мне было нужно. Вы, вероятно, сэкономили мне часы безуспешных поисков, которых я действительно не могу сэкономить. +1

Kiruse 25.06.2012 21:48

Интересно, почему его называют «компрессором», если это некомпрессор. ржу не могу

matteo 07.05.2013 22:54

почти 5 лет спустя, все еще полезно. Спасибо. Я выгружаю большой JSON прямо на страницу, а не AJAX. предварительно сжимая его с помощью PHP и распаковывая обратно на стороне клиента JavaScript - я экономлю часть накладных расходов.

user257319 05.12.2014 22:05

Нужен ли нам бит <?php..? .. Я спрашиваю, потому что он передается в метод decompress.

Jus12 07.07.2016 10:00

я получаю 14:16:28.512 TypeError: e.replace is not a function[Weitere Informationen] jsxcompressor.min.js:19:12201

Bluscream 22.06.2018 15:17

БЛАГОДАРЮ ВАС! Очень помогло, 2 дня искал решение! Еще раз большое спасибо ...

Yohannes Kristiawan 07.09.2018 15:58

Мы только что выпустили пакет 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'});

Предоставьте пример на стороне клиента для декодирования строк, сжатых с помощью gzip.

Redsandro 26.03.2014 06:30
var inflate = require('pako/lib/inflate').inflate; var text = inflate(zipped, {to: 'string'}); @Redsandro, вот как я использую пако.
forresto 07.08.2016 01:03

Этот пример на стороне клиента бросает incorrect header check

duhaime 16.09.2019 21:15

Другие вопросы по теме