Golang中Zip格式[]byte内存解压报错求助
解决zlib解压Zip格式字节时的“invalid header”错误
我通过API获取到Zip格式的[]byte,需要在不落地文件的前提下解压成[]byte,之后重新压缩。但使用当前解压代码时触发错误:zlib: invalid header。相关代码及原始压缩字节的十六进制dump如下:
现有解压代码
func UnzipBytes(zippedBytes []byte) ([]byte, error) { reader := bytes.NewReader(zippedBytes) zipReader, err := zlib.NewReader(reader) if err != nil { return nil, err } defer zipReader.Close() p, err := ioutil.ReadAll(zipReader) if err != nil { return nil, err } return p, nil }
原始压缩代码
buffer := new(bytes.Buffer) zipWriter := zip.NewWriter(buffer) zipFile, err := zipWriter.Create(file.name) _, err = zipFile.Write(file.content)
zippedBytes十六进制dump
00059350 78 b4 5b 0d 2b 81 c2 87 35 76 1b 11 4a ec 07 d1 |x.[.+...5v..J...| 00059360 76 77 a2 e1 3b d9 12 e2 51 d4 c5 bd 4b 2f 09 da |vw..;...Q...K/..| 00059370 f7 21 c7 26 73 1f 8e da f0 ff a3 52 f6 e2 00 e6 |.!.&s......R....|
错误原因
你混淆了两种完全不同的压缩格式:
zip.NewWriter生成的是标准Zip归档文件(包含文件元数据、目录结构等,是一个完整的归档容器)zlib.NewReader只能处理zlib格式的单压缩流(仅包含原始数据的压缩结果,带zlib特定头信息)
用zlib去解析Zip归档,自然会报头无效的错误。
修复方案
1. 使用正确的Zip解压方式
改用Go标准库archive/zip的NewReader来解析Zip格式字节,示例代码如下:
import ( "archive/zip" "bytes" "io" "io/ioutil" ) func UnzipBytes(zippedBytes []byte) ([]byte, error) { reader := bytes.NewReader(zippedBytes) // 第二个参数是Zip归档的总大小,直接用字节切片长度即可 zipReader, err := zip.NewReader(reader, int64(len(zippedBytes))) if err != nil { return nil, err } // 假设Zip归档中仅包含一个文件,根据实际业务调整 if len(zipReader.File) == 0 { return nil, io.EOF // 或者自定义空归档错误 } targetFile := zipReader.File[0] fileContentReader, err := targetFile.Open() if err != nil { return nil, err } defer fileContentReader.Close() content, err := ioutil.ReadAll(fileContentReader) if err != nil { return nil, err } return content, nil }
2. 补全原始压缩代码的收尾步骤
你的原始压缩代码缺少zipWriter.Close()调用,这会导致生成的Zip归档不完整(缺失归档尾部的中央目录记录),即使解压代码正确也可能出错。必须补充该调用:
buffer := new(bytes.Buffer) zipWriter := zip.NewWriter(buffer) zipFile, err := zipWriter.Create(file.name) if err != nil { // 处理创建文件错误 return err } _, err = zipFile.Write(file.content) if err != nil { // 处理写入错误 return err } // 必须调用Close完成归档写入,否则buffer中的数据不完整 err = zipWriter.Close() if err != nil { // 处理关闭错误 return err } // 此时buffer中的字节才是完整的Zip归档 zippedBytes := buffer.Bytes()
内容的提问来源于stack exchange,提问作者Bouramas
相关产品推荐
相关产品推荐

