PHP 无法通过 Golang 解压 gzip 数据
PHP can't decompress gzip data by Golang
为什么我的PHPdemo中Go无法解压gzip数据,但是PHPgzip数据转Go却成功了?我需要 post gzip JSON 数据从转到 PHP API 服务。
测试结果
-> | 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 失败。
去代码
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 去吧。
它适用于以下更改:
- 在您的 PHP 代码中,您想使用
gzdecode
而不是 gzinflate
。如果您使用它,则不需要 substr($data, 10)
东西。我没有读过 deflate 与 gzip 的关系,但简单的是 gzencode
/gzdecode
匹配 golang gzip
包的功能以及 GNU gz*
系列的功能命令行工具可以。
- 在您的 Go 代码中,将您的 gzip.Writer.Close() 调用移动到您从
buffer
读取之前完成。正如您在此处看到的:http://golang.org/src/compress/gzip/gzip.go?s=6230:6260#L240 关闭时还有一些其他内容会写入基础流,因此在您上面的示例中,您所写的内容是不完整的。 (在包含函数退出后,defer
语句导致 Close()
变为 运行。)Go gzip 解码很可能设法解码,而 PHP 实现不是 -在任何情况下,您都应该正确地关闭内存缓冲区中的流,以确保在将其写入文件之前它是完整的。
必须注意:您忽略了 Go 代码中的所有错误。这段代码看起来只是一个测试,所以我不会强调这一点,但您肯定希望进行正确的错误处理(向用户或函数的调用者报告问题)。
为什么我的PHPdemo中Go无法解压gzip数据,但是PHPgzip数据转Go却成功了?我需要 post gzip JSON 数据从转到 PHP API 服务。
测试结果
-> | 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 失败。
去代码
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 去吧。
它适用于以下更改:
- 在您的 PHP 代码中,您想使用
gzdecode
而不是gzinflate
。如果您使用它,则不需要substr($data, 10)
东西。我没有读过 deflate 与 gzip 的关系,但简单的是gzencode
/gzdecode
匹配 golanggzip
包的功能以及 GNUgz*
系列的功能命令行工具可以。 - 在您的 Go 代码中,将您的 gzip.Writer.Close() 调用移动到您从
buffer
读取之前完成。正如您在此处看到的:http://golang.org/src/compress/gzip/gzip.go?s=6230:6260#L240 关闭时还有一些其他内容会写入基础流,因此在您上面的示例中,您所写的内容是不完整的。 (在包含函数退出后,defer
语句导致Close()
变为 运行。)Go gzip 解码很可能设法解码,而 PHP 实现不是 -在任何情况下,您都应该正确地关闭内存缓冲区中的流,以确保在将其写入文件之前它是完整的。
必须注意:您忽略了 Go 代码中的所有错误。这段代码看起来只是一个测试,所以我不会强调这一点,但您肯定希望进行正确的错误处理(向用户或函数的调用者报告问题)。