go解压tar.gz需先用gzip.newreader包装再传tar.newreader,否则报invalid tar header;zip写中文路径须设flags: 0x800启用utf-8;内存打包zip必须调close()写central directory,tar则需write空数据确保header写入。

Go 里解压 tar.gz 文件总报 archive/tar: invalid tar header
常见原因是没跳过 gzip 层直接读 tar,或者文件开头有非 tar 数据(比如 HTTP 响应头)。archive/tar 本身不处理压缩,它只认原始 tar 流。
正确做法是先用 gzip.NewReader 包一层,再传给 tar.NewReader:
gz, _ := gzip.NewReader(file)
tr := tar.NewReader(gz)
for {
hdr, err := tr.Next()
if err == io.EOF { break }
// 处理 hdr.Name, tr.Read()...
}
- 别对 .tar.gz 文件直接
os.Open后塞给tar.NewReader—— 这是最高频的错 - 如果源是网络响应(如
*http.Response.Body),确保没提前调用resp.Body.Read(),否则 gzip 解包会失败 -
tar.Header.Size是 int64,用io.CopyN或循环读时注意类型匹配,别传int(hdr.Size)丢精度
用 archive/zip 写入中文路径文件时乱码或无法解压
Zip 规范本身不强制支持 UTF-8,老解压工具(如 Windows 自带解压器)默认按系统编码(GBK/Shift-JIS)解路径。Go 的 archive/zip 默认用原始字节写路径,不自动设 UTF-8 标志位。
解决方法只有两个:要么放弃中文路径,要么手动开启 ZIP64 + UTF-8 标志:
立即学习“go语言免费学习笔记(深入)”;
fw, _ := zip.CreateHeader(&zip.FileHeader{
Name: "中文/文件.txt",
Method: zip.Deflate,
Flags: 0x800, // UTF-8 flag
})
-
Flags: 0x800是关键,不是可选配置项 —— 漏了就等于没开 UTF-8 - Windows 资源管理器从 Win10 1803 开始才真正支持该标志,旧系统仍可能显示乱码
- 别试图用
filepath.FromSlash或strings.Replace“修复”路径分隔符 —— zip 规范要求路径用/,硬转\会导致跨平台失效
想把内存里的 []byte 打包成 tar 或 zip,但不想写临时文件
可以,但要注意 archive/tar 和 archive/zip 都依赖 io.Writer 接口,直接往 bytes.Buffer 写就行。不过 zip 有额外约束:必须在所有文件写完后调用 w.Close(),否则末尾的 central directory 会缺失,导致解压失败。
var buf bytes.Buffer
zw := zip.NewWriter(&buf)
fw, _ := zw.Create("data.json")
fw.Write([]byte(`{"id":1}`))
zw.Close() // 必须!否则 buf.Bytes() 得到的是损坏 zip
- tar 没这个限制 ——
tar.Writer.Close()只是写个结尾块,不写也大概率能解(但不符合规范) - 如果后续要把
buf.Bytes()当 HTTP 响应体发出去,记得设Content-Length,别用Transfer-Encoding: chunked—— 某些客户端 zip 解包器对流式 zip 支持差 - 别用
bufio.Writer包裹bytes.Buffer再传给 zip/tar —— 缓冲可能导致Close()后数据还没刷出
为什么 tar.WriteHeader 返回 nil 却实际没写成功?
因为 tar.Writer 是缓冲型写入器,WriteHeader 只把 header 放进缓冲区,真写入要靠后续的 Write 或显式 Flush。如果只调 WriteHeader 就结束,header 就丢了。
- 典型场景:想写一个空文件,只调
tw.WriteHeader(hdr),没跟tw.Write(nil)—— 解压时该文件会消失 - 安全写法是:写 header 后,立刻用
tw.Write(data)(哪怕data是nil或空切片) - 如果写完所有内容忘了
tw.Close(),最后的两个零字节 record(tar 结尾标记)不会写入,部分解包器会报 “truncated tar”










