JavaScript triển khai Gzip [đã đóng]


208

Tôi đang viết một ứng dụng Web cần lưu trữ dữ liệu JSON trong một bộ đệm nhỏ phía máy chủ có kích thước cố định thông qua AJAX (nghĩ: Hạn ngạch xã hội ). Tôi không có quyền kiểm soát máy chủ.

Tôi cần giảm kích thước của dữ liệu được lưu trữ trong phạm vi hạn ngạch phía máy chủ và hy vọng có thể giải nén JSON được xâu chuỗi trong trình duyệt trước khi gửi lên máy chủ.

Tuy nhiên, tôi không thể tìm thấy nhiều trong cách triển khai JavaScript của Gzip. Bất kỳ đề xuất nào về cách tôi có thể nén dữ liệu ở phía máy khách trước khi gửi nó lên?


6
Bạn đang gửi nó lên đến máy chủ. Đó là lý do tại sao có các khái niệm "tải lên" và "tải xuống". Có lẽ đó là lý do tại sao bạn nhận được câu trả lời cho bạn biết "máy chủ có thể làm được".
Tomalak

3
Việc thực hiện đúng cách này có lẽ là khó khăn, vì javascript là một luồng đơn. Nó có thể sẽ phải nén theo đợt, sử dụng setTimeout (), để UI không bị khóa trong khi nén.
Tháng 8 Lilleaas

có lẽ bạn có thể viết thuật toán nén của riêng mình
Thuyền trưởng KurO

3
@AugustLilleaas bây giờ bạn có thể sử dụng webworkers để làm điều này :)
Captain Rõ ràng

Câu trả lời:


138

Chỉnh sửa Dường như có một giải pháp LZW tốt hơn để xử lý chính xác các chuỗi Unicode tại http://pieroxy.net/blog/pages/lz-opes/index.html (Nhờ vào pieroxy trong các nhận xét).


Tôi không biết về bất kỳ triển khai gzip nào, nhưng thư viện jsolait (trang web dường như đã biến mất) có chức năng nén / giải nén LZW. Mã được bảo hiểm theo 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
Theo Wikipedia, bằng sáng chế đã hết hạn vài năm trước. Nó có thể là một ý tưởng tốt để kiểm tra xem mặc dù.
Matthew Crumley

3
LZW đã quá cũ để vẫn được cấp bằng sáng chế. Bằng sáng chế cuối cùng đã hết trong năm 2003 hoặc lâu hơn. Có rất nhiều triển khai miễn phí.
ypnos

5
Tôi thấy ít nhất hai sự cố với mã ở trên: 1) thử nén "Kiểm tra để nén này \ u0110 \ u0111 \ u0112 \ u0113 \ u0114 không phải ký tự.", 2) Không có lỗi nào được báo cáo nếu mã> 65535.
một số lỗi

5
Dưới đây là các triển khai bằng 21 ngôn ngữ khác nhau rosettacode.org/wiki/LZW_compression, nó được viết rằng nó thuộc phạm vi công cộng từ năm 2004.
jcubic

5
@some Tôi vừa phát hành một lib nhỏ sửa chính xác các vấn đề bạn đang chỉ ra ở đây: pieroxy.net/blog/pages/lz-opes/index.html
pieroxy

53

Tôi gặp một vấn đề khác, tôi không muốn mã hóa dữ liệu trong gzip nhưng để giải mã dữ liệu được nén . Tôi đang chạy mã javascript bên ngoài trình duyệt vì vậy tôi cần giải mã nó bằng cách sử dụng javascript thuần túy .

Phải mất một thời gian nhưng tôi thấy rằng trong thư viện JSXGraph có một cách để đọc dữ liệu được nén.

Đây là nơi tôi tìm thấy thư viện: http://jsxgraph.uni-bayreuth.de/wp/2009/09/29/jsxcompressor-zlib-compression-javascript-code/ Thậm chí còn có một tiện ích độc lập có thể làm điều đó, JSXCompressor và mã được LGPL cấp phép.

Chỉ cần bao gồm tệp jsxcompressor.js trong dự án của bạn và sau đó bạn sẽ có thể đọc dữ liệu được mã hóa 64 cơ sở:

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

Tôi hiểu đó không phải là điều bạn muốn nhưng tôi vẫn trả lời ở đây vì tôi nghi ngờ nó sẽ giúp được một số người.


3
Cảm ơn bạn rất nhiều vì vẫn chia sẻ. Đây chính xác là những gì tôi cần. Có lẽ bạn đã tiết kiệm cho tôi hàng giờ tìm kiếm không thành công mà tôi thực sự không thể tha thứ. +1
Kiruse

1
Tôi tự hỏi tại sao trên trái đất nó được gọi là "máy nén" khi nó là một UNcompressor. lol
matteo

1
Gần 5 năm sau, vẫn hữu dụng. cảm ơn bạn. Tôi đang đổ một JSON lớn trực tiếp vào trang, thay vì AJAX'ing nó. bằng cách nén trước nó bằng PHP và giải nén nó ở phía máy khách của JavaScript - Tôi đang tiết kiệm một số chi phí.

Chúng ta có cần <?php..bit không? .. Tôi đang hỏi bởi vì nó được truyền cho decompressphương thức.
Jus12

tôi nhận được14:16:28.512 TypeError: e.replace is not a function[Weitere Informationen] jsxcompressor.min.js:19:12201
Bluscream

40

Chúng tôi vừa phát hành pako https://github.com/nodeca/pako , cổng zlib sang javascript. Tôi nghĩ rằng đó là cách thực hiện js nhanh nhất của deflate / Inflate / gzip / ungzip. Ngoài ra, nó có giấy phép MIT dân chủ. Pako hỗ trợ tất cả các tùy chọn zlib và kết quả của nó là nhị phân bằng nhau.

Thí dụ:

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

7
Vui lòng cung cấp một ví dụ phía máy khách để giải mã các chuỗi được nén.
Redsandro

2
var inflate = require('pako/lib/inflate').inflate; var text = inflate(zipped, {to: 'string'});@Redsandro đây là cách tôi sử dụng pako.
forresto

Ví dụ khách hàng đó némincorrect header check
duhaime

17

Tôi đã chuyển việc triển khai LZMA từ mô-đun GWT sang JavaScript độc lập. Nó được gọi là LZMA-JS .


1
Bạn có một mô-đun php tương thích cho nó?
Sirber

rằng url là 404, và tôi không thể tìm thấy nó trên github.com/nmrugg hoặc
hanshenrik

Xin lỗi, liên kết đã thay đổi. Đây là cái mới: lzma-js.github.io/LZMA-JS

14

Dưới đây là một số thuật toán nén khác được triển khai trong Javascript:


việc triển khai LZMA này yêu cầu BrowserPlus (một phần mở rộng trình duyệt) và không có vẻ là Javascript thuần túy
Piotr Findeisen

triển khai LZ77 này không còn khả dụng và ít nhất đó là phiên bản Python (được xuất bản trên cùng một trang) không chính xác cho các đầu vào khá đơn giản.
Piotr Findeisen

địa lý đã chết, sẽ cập nhật liên kết
Mauricio Scheffer

Điều này là khá gần với những gì tôi muốn. những điều googling cũng sẽ cập nhật ở đây
Theofanis Pantelides


0

Tôi đoán việc triển khai nén JavaScript phía máy khách chung sẽ là một hoạt động rất tốn kém về thời gian xử lý, trái với thời gian chuyển của một vài gói HTTP với tải trọng không nén.

Bạn đã thực hiện bất kỳ thử nghiệm nào sẽ cho bạn ý tưởng cần tiết kiệm bao nhiêu thời gian chưa? Ý tôi là, tiết kiệm băng thông không thể là thứ bạn theo đuổi, hay có thể?


Tôi cần giữ tổng kích thước dữ liệu trong một hạn ngạch nhất định - kích thước quan trọng hơn thời gian.
David Citron

Hừm ... Tại sao lại là giới hạn? Chỉ tò mò thôi.
Tomalak

Chà, đây là Google đảm nhận: code.google.com/apis/opensocial/articles/ hạng - Hạn ngạch Opensocial điển hình là khoảng 10K.
David Citron

Tôi thấy, cảm ơn đã làm rõ.
Tomalak

1
Tùy thuộc vào mức độ nén sâu, bạn có thể sử dụng nhân viên web để thực hiện tác vụ phía sau hậu trường.
zachleat

-3

Hầu hết các trình duyệt có thể giải nén gzip khi đang di chuyển. Đó có thể là một lựa chọn tốt hơn so với triển khai javascript.


20
Có, nhưng tôi cần nén dữ liệu ở phía máy khách trước khi gửi nó xuống ...
David Citron

-4

Bạn có thể sử dụng một applet Java 1 pixel trên 1 pixel được nhúng trong trang và sử dụng nó để nén.

Đó không phải là JavaScript và các máy khách sẽ cần một thời gian chạy Java nhưng nó sẽ làm những gì bạn cần.


7
Thú vị, nhưng tôi muốn tránh bao gồm một applet nếu có thể.
David Citron

Tôi muốn thêm các trường hợp sử dụng thực tế
cmc

1
Không phải là một giải pháp tốt vì nó thêm một phụ thuộc vào Java. Ngoài ra, không phải ai cũng bận tâm cài đặt java - trang web sẽ không hoạt động đối với một số người. Cá nhân tôi đã cài đặt java vì tôi cần nó từ lâu rồi, nhưng tôi thích truy cập các trang web không sử dụng java.
Onkelborg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.