Почему не удается распаковать gzip-данные Go в моей демо-версии PHP, но данные gzip PHP для Go успешно? Мне нужно отправлять данные gzip JSON из 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.
Код go
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)) }
Этот результат: Go to Go okay. PHP идти в порядке.
Он работает со следующими изменениями:
gzdecode
вместо gzinflate
. И вы не нуждаетесь в этом substr($data, 10)
если используете это. Я не читал о том, как deflate относится к gzip, но простота в том, что gzencode
/ gzdecode
соответствует тому, что делает пакет golip golang, и что делает gz*
семейство инструментов командной строки GNU. buffer
. Как вы можете видеть здесь: http://golang.org/src/compress/gzip/gzip.go?s=6230:6260#L240 есть некоторые дополнительные материалы, которые записываются в базовый поток при закрытии, поэтому в вашем примере выше того, что вы пишете, является неполным. (Оператор defer
заставляет Close()
запускаться после выхода из функции сохранения.) Скорее всего, декодирование Go gzip все равно декодирует, тогда как реализация PHP не является – в любом случае вы должны правильно закрыть поток в своем буфере памяти чтобы убедиться, что он завершен, прежде чем записывать его в файл. ОБЯЗАТЕЛЬНОЕ ПРИМЕЧАНИЕ: вы игнорируете все свои ошибки в коде Go. Этот код выглядит просто как тест, поэтому я не буду расстраивать этот вопрос, но вы определенно хотите выполнять правильную обработку ошибок (либо сообщая о проблеме пользователю, либо вызывающему абоненту вашей функции).