猿问

Golang:“压缩/扁平化”模块无法解压缩有效的 deflate 压缩 HTTP 正文

这个问题延续了这里开始的讨论。我发现 HTTP 响应正文由于deflate后者的压缩而无法解组为 JSON 对象。现在我想知道如何使用 Golang 进行解压。我将感谢任何可以在我的代码中显示错误的人。


输入数据


我已将 HTTP 响应正文转储到“测试”文件中。就这个:


$ cat test

x��PAN�0�

;��NtJ�FӮdU�|"oVR�C%�f�����Z.�^Hs�dW뮑�'��DH�S�SFVC����r)G,�����<���z}�x_g�+�2��sl�r/�Oy>��J3\�G�9���N���#[5M�^v/�2Ҕ��|�h��[�~7�_崛<D*���/��i

让我们确保这个文件可以解压缩,甚至包含有效的 JSON:


$ zlib-flate -uncompress < test

{"timestamp":{"tv_sec":1428488670,"tv_usec":197041},"string_timestamp":"2015-04-08 10:24:30.197041","monitor_status":"enabled","commands":{"REVERSE_LOOKUP":{"cache":{"outside":{"successes":0,"failures":0,"size":0,"time":0},"internal":{"successes":0,"failures":0,"size":0,"time":0}},"disk":{"outside":{"successes":0,"failures":0,"size":0,"time":0},"internal":{"successes":13366,"failures":0,"size":0,"time":501808}},"total":{"storage":{"successes":0,"failures":0},"proxy":{"successes":13366,"failures":0}}},"clients":{}}}

$ zlib-flate -uncompress < test | python -m json.tool

{

    "commands": {

        "REVERSE_LOOKUP": {

            "cache": {

               ....

源代码


package main


import (

    "bytes"

    "compress/flate"

    "fmt"

    "io/ioutil"

)


func main() {

    fname := "./test"

    content, err := ioutil.ReadFile(fname)

    if err != nil {

        panic(err)

    }

    fmt.Println("File content:\n", content)


    enflated, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(content)))

    if err != nil {

        panic(err)

    }

    fmt.Println("Enflated:\n", enflated)

}

错误


$ go run uncompress.go 

panic: flate: corrupt input before offset 5


goroutine 1 [running]:

runtime.panic(0x4a7180, 0x5)

    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6

main.main()

    /home/isaev/side-projects/elliptics-manager/uncompress.go:20 +0x2a3

exit status 2

PS Ubuntu 14.10,转到 1.2.1


梵蒂冈之花
浏览 586回答 1
1回答

慕斯709654

您的输入不是一个简单的压缩块,而是一个zlib 流。根据ZLIB 压缩数据格式规范 3.3,前 2 个字节是:-------------| CMF | FLG |-------------压缩方法和标志。您的输入以十六进制的[120, 156]which开头78 9C。这是默认压缩。也没有字典跟随,所以后续数据是压缩数据。位 0 到 3 是 CM 压缩方法,位 4 到 7 是 CINFO 压缩信息。在这种情况下,CINFO=7 表示 32K 窗口大小,CM=8 表示“deflate”压缩方法。FLG 位 5 表示是否预设了字典,在这种情况下是。FLG 的详细信息也在链接的RFC 1950 中。所以你的输入基本上告诉其余的数据是使用默认压缩构造的,但是 goflate包不会解码它。更改您的解压缩以省略前 2 个字节,它会起作用:enflated, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(content[2:])))在Go Playground上试一试。但...使用正确的 ZLib 解压!这次我们很幸运,因为压缩级别是默认的,并且字典是预设的。如果没有,您将无法使用该flate包对其进行解码。由于输入是 zlib 流,因此您应该使用该compress/zlib包对其进行正确解码,而不要依赖运气:r, err := zlib.NewReader(bytes.NewReader(content))if err != nil {&nbsp; &nbsp; panic(err)}enflated, err := ioutil.ReadAll(r)if err != nil {&nbsp; &nbsp; panic(err)}fmt.Println(string(enflated))zlib在Go Playground上试试这个变体。
随时随地看视频慕课网APP

相关分类

Go
我要回答