Gzip的JavaScript实现


208

我正在编写一个Web应用程序,该应用程序需要通过AJAX将JSON数据存储在固定大小的小型服务器端缓存中(请考虑:Opensocial配额)。我无法控制服务器。

我需要减小存储数据的大小,以保持在服务器端配额之内,并希望能够在将字符串化的JSON发送到服务器之前在浏览器中gzip化该字符串化的JSON。

但是,我找不到Gzip的JavaScript实现方式。关于如何在发送之前在客户端上压缩数据的任何建议?


6
您在发送服务器。这就是为什么存在“上传”和“下载”概念的原因。也许这就是为什么您得到的答案告诉您“服务器可以做到”的原因。
Tomalak

3
由于javascript是单线程的,因此适当的实现可能会比较棘手。它可能必须使用setTimeout()进行批量压缩,以使UI不会在压缩时锁定。
2009年

也许您可以编写自己的压缩算法
kurO队长2012年

3
@AugustLilleaas,现在您可以使用网络工作人员来做这个:)
上尉船长

Answers:


138

编辑http://pieroxy.net/blog/pages/lz-string/index.html上,似乎有更好的LZW解决方案可以正确处理Unicode字符串(感谢注释中的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
开始

5
@some我刚刚发布了一个小的lib来纠正您在此指出的问题:pieroxy.net/blog/pages/lz-string/index.html
pieroxy 2013年

53

我还有另一个问题,我不想用gzip编码数据,而是想解码gzip的数据。我在浏览器外部运行javascript代码,因此我需要使用 JavaScript 对其进行解码。

我花了一些时间,但是我发现JSXGraph库中有一种读取压缩数据的方法。

在这里找到了该库:http : //jsxgraph.uni-bayreuth.de/wp/2009/09/29/jsxcompressor-zlib-compressed-javascript-code/ 甚至还有一个独立的实用工具JSXCompressor,并且该代码已获得LGPL许可。

只要在您的项目中包含jsxcompressor.js文件,您就可以读取以64为基数的gzip压缩数据:

<!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
Kiruse 2012年

1
我想知道为什么当它是UNcompressor时为什么被称为“压缩机”。大声笑
matteo

1
差不多5年后,仍然有用。谢谢。我将大型JSON直接转储到页面,而不是AJAX。通过用PHP预压缩并在JavaScript的客户端将其解压缩-我节省了一些开销。

我们需要<?php..位吗?我问,因为它已传递给decompress方法。
2016年

我得到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的端口)。我认为这是deflate / inflate / gzip / ungzip最快的js实现。此外,它还拥有民主的MIT许可证。Pako支持所有zlib选项,其结果是二进制相等的。

例:

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

7
请提供用于解码压缩字符串的客户端示例。
Redsandro 2014年

2
var inflate = require('pako/lib/inflate').inflate; var text = inflate(zipped, {to: 'string'});@Redsandro这是我使用pako的方式。
forresto

该客户端示例引发了问题incorrect header check
duhaime


14

这是用Javascript实现的其他一些压缩算法:


此LZMA实现需要使用BrowserPlus(浏览器扩展),而且看起来不是纯Javascript
Piotr Findeisen,2009年

该LZ77实现不再可用,至少对于相当简单的输入而言,它的Python版本(在同一页面上发布)至少是错误的。
Piotr Findeisen,2009年

地质死者,将更新链接
Mauricio Scheffer

这非常接近我想要的。谷歌搜索内容也会在这里更新
Theofanis Pantelides


0

我猜想就处理时间而言,通用的客户端JavaScript压缩实现将是一个非常昂贵的操作,而不是另外一些带有未压缩有效负载的HTTP数据包的传输时间。

您是否进行了任何测试以使您知道节省多少时间?我的意思是,节省带宽不是您所追求的,不是吗?


我需要将总数据大小保持在一定的配额之内-大小比时间更重要。
David Citron

嗯...为什么是极限?只是好奇。
Tomalak

好吧,这是Google的做法:code.google.com/apis/opensocial/articles/…-典型的Opensocial配额约为1万。
David Citron

我明白了,谢谢您的澄清。
Tomalak

1
根据压缩的强度,您可以使用Web Worker在后台执行任务。
zachleat 2010年

-3

大多数浏览器可以即时解压缩gzip。这可能比javascript实现更好。


20
是的,但是我需要先压缩客户端上的数据,然后再向下发送...
David Citron

-4

您可以使用页面中嵌入的每1像素Java小程序1像素并将其用于压缩。

它不是JavaScript,客户端将需要Java运行时,但是它将满足您的需求。


7
有趣,但我宁愿避免在可能的情况下包含小程序。
David Citron

我想添加实际用例
cmc 2012年

1
这不是一个好的解决方案,因为它增加了对Java的依赖。除此之外,并不是每个人都愿意安装Java-该网站对某些人来说不起作用。我个人已经安装了Java,因为很久以前就需要它,但是我更喜欢访问不使用Java的网站。
Onkelborg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.