PHP无法通过Golang解压缩gzip数据 [英] PHP can't decompress gzip data by Golang

查看:228
本文介绍了PHP无法通过Golang解压缩gzip数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在我的PHP演示中无法通过Go解压缩gzip数据,但是成功将PHP gzip数据解压到Go?我需要从Go to PHP API服务发布gzip JSON数据.

Why can't decompress gzip data by Go in my PHP demo, but PHP gzip data to Go is successful? I need post gzip JSON data from Go to PHP API service.

测试结果

 -> |  php   |  go 
---------------------
php |  ok    |  ok
go  |  fail  |  ok

PHP代码

class GzipDemo
{
    public function gzen($data, $file){
       $json_data = json_encode($data);
       $gz_data = gzencode($json_data,9);
       file_put_contents($file,$gz_data);
    }

    public function gzdn($file){
       $data = file_get_contents($file);
        $unpacked = gzdecode($data);
        if ($unpacked === FALSE)
        {
            print("failed:".$file."\n");
        }else{
             print($file. " result Data :".$unpacked ."\n");
        }
    }
}

$demo = new GzipDemo();
$file="phpgzip.txt";
$demo->gzen("data",$file);
$demo->gzdn($file);
$demo->gzdn("gogzip.txt");

此结果: PHP到PHP可以. 转到PHP失败.

This result: PHP to PHP okay. Go to PHP fail.

执行代码

package main

import (
    "bytes"
    "compress/gzip"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    gzen("data", "gogzip.txt")
    gden("gogzip.txt")
    gden("phpgzip.txt")
}
func gzen(data string, file string) {
    b, _ := json.Marshal(data)
    buffer := new(bytes.Buffer)
    w, _ := gzip.NewWriterLevel(buffer, gzip.BestCompression)
    defer w.Close()
    w.Write(b)
    w.Flush()
    ioutil.WriteFile(file, buffer.Bytes(), os.ModePerm)
}
func gden(file string) {
    b, _ := ioutil.ReadFile(file)
    buffer := new(bytes.Buffer)
    buffer.Write(b)
    r, _ := gzip.NewReader(buffer)
    defer r.close()
    data, _ := ioutil.ReadAll(r)
    fmt.Println(file, " result Data:", string(data))
}

此结果: 去吧,好吧. PHP可以了.

This result: Go to Go okay. PHP to Go okay.

推荐答案

它适用于以下更改:

  • 在您的PHP代码中,您想使用gzdecode而不是gzinflate.而且,如果您使用substr($data, 10)这些东西,则不需要它们.我没有读过deflate与gzip的关系,但简单之处在于gzencode/gzdecode与golang gzip软件包的功能以及gz*系列GNU命令行工具的功能匹配.
  • 在您的Go代码中,请先移动gzip.Writer.Close()调用,然后再从buffer中读取内容.如您所见: http://golang.org /src/compress/gzip/gzip.go?s=6230:6260#L240 还有一些其他内容会在关闭时写入基础流,因此在上面的示例中,您编写的内容是不完整的. (defer语句使Close()在包含函数退出后运行.)很可能Go gzip解码无论如何都设法解码,而PHP实现却没有-在任何情况下,您都应该正确地关闭流向in内存缓冲区,以确保在将其写出到文件之前是完整的.
  • In your PHP code you want to use gzdecode instead of gzinflate. And you don't need this substr($data, 10) stuff if you use that. I didn't read up on how deflate relates to gzip but the simplicity is that gzencode/gzdecode match what the golang gzip package does and what the gz* family of GNU command line tools do.
  • In your Go code move your gzip.Writer.Close() call to be done before you read from buffer. As you can see here: http://golang.org/src/compress/gzip/gzip.go?s=6230:6260#L240 there is some additional stuff that is written to the underlying stream upon close, so in your example above what you are writing is incomplete. (The defer statement causes Close() to be run after the containing function exits.) Most likely the Go gzip decoding is managing to decode anyway whereas the PHP implementation is not - in any case you should properly close the stream to your in memory buffer to ensure it is complete before writing it out to a file.

强制性注释:您将忽略Go代码中的所有错误.这段代码看起来只是一个测试,所以我不会太在意这一点,但是您绝对希望进行适当的错误处理(向用户或函数的调用者报告问题).

OBLIGATORY NOTE: You are ignoring all of your errors in your Go code. This code looks like just a test so I won't belabor the point but you definitely want to be doing proper error handling (either reporting the problem to the user or to the caller of your function).

这篇关于PHP无法通过Golang解压缩gzip数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆