简体   繁体   English

JavaScript Zlib解压缩

[英]JavaScript Zlib Decompress

I'm trying to decompress zlib'ed XML such as the following: https://drive.google.com/file/d/0B52P0MZLTdw8ZzQwQzVpZGZVZWc 我正在尝试解压缩zlib的XML,如下所示: https ://drive.google.com/file/d/0B52P0MZLTdw8ZzQwQzVpZGZVZWc

Uploading to online decompress services works, such as: http://i-tools.org/gzip 上传到在线解压缩服务的工作,例如: http//i-tools.org/gzip

In PHP, I'm using this code and works just fine, I get the XML string: 在PHP中,我使用此代码并且工作正常,我得到XML字符串:

$raw = file_get_contents("file_here");
$uncompressed = zlib_decode($raw);

However, I want to do this in JavaScript. 但是,我想在JavaScript中执行此操作。

  • The app is a client-side Chrome extension which uses chrome.devtools.network that reads from the network logs 该应用是客户端Chrome扩展程序,它使用chrome.devtools.network从网络日志中读取
  • Reads binary responses. 读取二进制响应。 Example at Google Drive link at the top 顶部的Google云端硬盘链接示例
  • JS needs to decompress that response to its original XML and parsed afterwards into object JS需要将该响应解压缩到其原始XML,然后解析为对象

The only problem I have is the zlib decompress part. 我唯一的问题是zlib解压缩部分。

As of Latest Update, the Decompression Libraries work but unpacking doesn't. 截至最新更新,解压缩库工作但解压缩不起作用。 Please skip to the Update Sept 16 at the bottom. 请跳至底部的更新9月16日。


I have already tried several JavaScript libraries and still cannot make it work: 我已经尝试了几个JavaScript库,仍然无法使其工作:

Pako : https://github.com/nodeca/pako Pakohttps//github.com/nodeca/pako

unpack() code: https://codereview.stackexchange.com/questions/3569/pack-and-unpack-bytes-to-strings unpack()代码: https//codereview.stackexchange.com/questions/3569/pack-and-unpack-bytes-to-strings

function unpack(str) {
    var bytes = [];
    for(var i = 0, n = str.length; i < n; i++) {
        var char = str.charCodeAt(i);
        bytes.push(char >>> 8, char & 0xFF);
    }
    return bytes;
}

$.get("file_here", function(response){
    var charData    = unpack(response);
    var binData     = new Uint8Array(charData);
    var data        = pako.inflate(binData);
    var strData     = String.fromCharCode.apply(null, new Uint16Array(data));
    console.log(strData);
});

Error: Uncaught incorrect header check 错误: Uncaught incorrect header check

It's the same even placing the response elsewhere: 将响应放在其他地方也是如此:

  • new Uint8Array(response);
  • pako.inflate(response);

Imaya's zlib : https://github.com/imaya/zlib.js Imaya的zlibhttps//github.com/imaya/zlib.js

$.get("file_here", function(response){
    var inflate = new Zlib.Inflate(response);
    var output = inflate.decompress();
    console.log(output);
});

Error: Uncaught Error: unsupported compression method inflate.js:60 错误: Uncaught Error: unsupported compression method inflate.js:60

Still using Imaya's zlib, combining with this Stack Overflow question: Decompress gzip and zlib string in javascript 仍然使用Imaya的zlib,结合这个Stack Overflow问题: 在javascript中解压缩gzip和zlib字符串

$.get("file_here", function(response){
    var response = response.split('').map(function(e) {
        return e.charCodeAt(0);
    });
    var inflate = new Zlib.Inflate(response);
    var output = inflate.decompress();
    console.log(output);
});

Error: Uncaught Error: invalid fcheck flag:29 inflate.js:65 错误: Uncaught Error: invalid fcheck flag:29 inflate.js:65


dankogai's js-deflate : https://github.com/dankogai/js-deflate dankogai的js-deflatehttps//github.com/dankogai/js-deflate

console.log(RawDeflate.inflate(response));

Output: 输出: empty


augustl's js-inflate : https://github.com/augustl/js-inflate augustl的js-inflatehttps//github.com/augustl/js-inflate

console.log(JSInflate.inflate(response));

Output: 输出: empty


zlib-browserify : https://github.com/brianloveswords/zlib-browserify zlib-browserifyhttps//github.com/brianloveswords/zlib-browserify

Error: ReferenceError: exports is not defined 错误: ReferenceError: exports is not defined

This is just a wrapper for Imaya's zlib. 这只是Imaya的zlib的包装器。 I think this is requireJS ? 我认为这是requireJS I'm not even sure how to use it. 我甚至不确定如何使用它。 Can it even be used without installing anything and just jQuery/JS? 它甚至可以在没有安装任何东西的情况下使用,只需jQuery / JS吗? The app as mentioned is downloadable Chrome extension with just HTML importing JS files. 提到的应用程序是可下载的Chrome扩展程序,只有HTML导入JS文件。


UPDATE Sept 16, 2014 更新于2014年9月16日

It seems the problem is with the JavaScript unpack( ) function. 看来问题出在JavaScript unpack( )函数上。 When I use the ByteArray generated by PHP: http://pastebin.com/uDWvK94B , the JavaScript decompression functions work. 当我使用PHP生成的ByteArray: http//pastebin.com/uDWvK94B时 ,JavaScript解压缩功能起作用。

PHP unpacking that works: PHP拆包工作:

$unpacked = unpack("C*", $raw);

For the JavaScript unpack( ) code that I use, which doesn't work, see top of the post under Pako section. 对于我使用的JavaScript unpack( )代码,这不起作用,请参阅Pako部分下的帖子顶部。

So the new question is, why does JavaScript generate a different ByteArray values than the one generated by PHP. 所以新问题是,为什么JavaScript会生成与PHP生成的值不同的ByteArray值。

  • Is it really a problem with the unpack( ) function? 这是unpack( )函数的问题吗?
  • or is it something when the JS fetches the file, the encoding or whatsoever changes thus bytes get messed up? 或者它是什么时候JS获取文件,编码或任何改变因此字节搞砸了?
  • and lastly, what is your suggested fix? 最后,你建议的修复是什么?

UPDATE Sept 20, 2014 更新于2014年9月20日

With more research and some of the answers here giving leads 随着更多的研究和一些答案在这里提供线索

  • Sebastian S opening the idea that the problem was in the manner of retrieving data and it had something to do with text encodings Sebastian S认为问题在于检索数据的方式,并且与文本编码有关
  • user3995789 providing an example that it will work even without the unpack( ) function, though outside the context of Chrome extensions user3995789提供了一个示例,即使没有unpack( )函数也可以使用它,但在Chrome扩展的上下文之外
  • Isaac providing examples in the context of Chrome extensions, but still does not work Isaac在Chrome扩展程序的上下文中提供了示例,但仍然不起作用

With that I researched further combining all leads which lead me to a theory that the reason behind all this is that Chrome is unable to get "raw" data through its request.getContent function. 有了这个,我研究了进一步结合所有线索,这引出了一个理论,这背后的原因是Chrome无法通过其request.getContent函数获得“原始”数据。 See here for the Chrome documentation for the said function. 请参阅此处了解所述功能的Chrome文档。

As of now, I have taken the issue to Chrome, see here . 截至目前,我已将问题提交给Chrome, 请参阅此处

UPDATE March 24, 2015 更新2015年3月24日

Although the problem was not fully resolved, the answer which I think was the most useful to me was from @Sebastian S, who proposed that "the way" I was taking or receiving the data was at fault and a bad conversion was the cause, which is as near as the problem was. 虽然问题没有得到彻底解决,但我认为最有用的答案来自@Sebastian S,他提出“我采取或接收数据的方式”是错误的,导致转换不良,这跟问题差不多。

Jquery reads in utf8 format, you have to read the raw file, this function will work. Jquery读取utf8格式,你必须读取原始文件,这个功能才有用。

function readTextFile(file)
{
    var rawFile = new XMLHttpRequest();
    rawFile.open('GET', file, true);  
    rawFile.responseType = 'arraybuffer';
    rawFile.onload = function (response)
    {
      var words = new Uint8Array(rawFile.response);
       console.log(words[1]);
      console.log(pako.ungzip(words));

    };
    rawFile.send();
}

For more information see this answer . 有关更多信息,请参阅此答案

I understood that you wanna use the zlib decompression inside a chrome extension while reading reponses bodies from the network log. 我知道你想在Chrome扩展中使用zlib解压缩,同时从网络日志中读取响应主体。

You need first to retrieve the base64 who will be decompressed. 您首先需要检索将被解压缩的base64。 You can achieve this while using the getContent method. 您可以在使用getContent方法时实现此目的。

function zlibDecompress(base64Content){
    // var base64Content        = base64Content.split(',')[1]; // Not sure if need to keep it

    // Decode base64 (convert ascii to binary)
    var strData     = atob(base64Content);

    // Convert binary string to character-number array
    var charData    = strData.split('').map(function(x){return x.charCodeAt(0);});

    // Turn number array into byte-array
    var binData     = new Uint8Array(charData);

    // Pako inflate
    var data        = pako.inflate(binData, { to: 'string' });

    return data;

}

chrome.devtools.network.onRequestFinished.addListener(
    function(request) {
        request.getContent(
            function(content, encoding){
                if(encoding == 'base64'){
                    var output = zlibDecompress(content);
                }
            }
        );
    }
);

https://developer.chrome.com/extensions/devtools_network#type-Request https://developer.chrome.com/extensions/devtools_network#type-Request

Using XMLHttpRequest : 使用XMLHttpRequest:

<script type="text/javascript" src="pako.js"></script>
<script type="text/javascript">

function zlibDecompress(url){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';

    xhr.onload = function(oEvent) {
        // Base64 encode
        var reader = new window.FileReader();
        reader.readAsDataURL(xhr.response); 
        reader.onloadend = function() {
            base64data      = reader.result;  
            var base64      = base64data.split(',')[1];

            // Decode base64 (convert ascii to binary)
            var strData     = atob(base64);

            // Convert binary string to character-number array
            var charData    = strData.split('').map(function(x){return x.charCodeAt(0);});

            // Turn number array into byte-array
            var binData     = new Uint8Array(charData);

            // Pako inflate
            var data        = pako.inflate(binData, { to: 'string' });

            console.log(data);
        }
    };

    xhr.send();
}
zlibDecompress('fileurl');
</script>

If you wanna use XMLHttpRequest with chrome extension 如果你想使用带有chrome扩展名的XMLHttpRequest

{
  "name": "My extension",
  ...
  "permissions": [
    "http://www.domain.com/", // The domain that hold the file
    "http://*/" // Or every domain
  ],
  ...
}

https://developer.chrome.com/extensions/xhr https://developer.chrome.com/extensions/xhr

Feel free to ask if you have any questions ;) 如果您有任何问题,请随时询问;)

In my opinion the question you should really be asking is: How do you retrieve the compressed data? 在我看来,你应该问的问题是: 你如何检索压缩数据? As soon as it becomes an UTF-16 string, the trouble begins. 一旦它成为UTF-16字符串,麻烦就开始了。 I'm not even sure, if the conversion from raw byte data to javascript strings is lossless. 我甚至不确定,如果从原始字节数据到javascript字符串的转换是无损的。

As you wrote something about php, I assume you're communicating to some sort of backend. 当你写一些关于php的东西时,我假设你正在与某种后端进行通信。 If this is true, there are options to handle binary data with native means. 如果这是真的,可以使用本机方法处理二进制数据。 Maybe this can help you: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data 也许这可以帮到你: https//developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM