gzip仅压缩单文件流,不处理目录打包;archive/zip支持多文件但需手动路径净化防Zip Slip;tar.gz须先tar后gzip嵌套,顺序错误将导致乱码。

gzip 只能压单个文件,别指望它打包目录
Go 的 compress/gzip 本质是压缩算法封装,不处理文件组织——它连“文件”概念都没有,只认 io.Reader 流。想用它压一个目录?会直接 panic 或生成损坏的 .gz 文件。
- 必须显式调用
gzWriter.Close(),否则尾部 CRC 和 ISIZE 写不进去,gunzip -t会报unexpected end of file - 解压时不能
os.Open后直接读二进制,得用gzip.NewReader()包一层再传给io.Copy - 压缩级别选
gzip.BestSpeed(适合日志)、gzip.DefaultCompression(通用),别用gzip.NoCompression除非你只是想套个壳
archive/zip 才是多文件打包正解,但路径一错就解压失败
archive/zip 支持多文件+目录,但不会自动递归遍历,也不会帮你清理路径——你传 "C:\foo\bar.txt" 进去,它真就照写,macOS 和 Linux 解压工具可能直接静默跳过。
- 所有路径必须转正斜杠:
filepath.ToSlash(relPath),比如"sub\file.txt"→"sub/file.txt" - 目录条目要手动加尾部斜杠:
header.Name = "dir/",否则解压端识别不了这是空目录 - 每个文件写入前必须设
header.Method = zip.Deflate,否则默认zip.Store(零压缩) -
zw.Close()不可省略,它负责写 ZIP 中央目录区,缺了就是非法 ZIP 文件
解压 ZIP 时不做路径校验,等于敞开系统文件被覆盖的大门
攻击者只要在 ZIP 里塞一个 "../../etc/passwd",你用 filepath.Join(outputDir, f.Name) 一拼,就可能把系统关键文件覆盖掉——这叫 Zip Slip 漏洞,Go 标准库不拦截,全靠你自己防。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 先做
cleanPath := filepath.Clean(f.Name),再检查cleanPath != f.Name || strings.HasPrefix(cleanPath, "..") - 目标路径必须严格落在输出目录下:
strings.HasPrefix(filepath.ToSlash(dstPath), filepath.ToSlash(absDest)) - 创建文件前,先
os.MkdirAll(filepath.Dir(dstPath), 0755),别等os.OpenFile报no such file or directory - 遇到
f.IsDir()就只os.MkdirAll,别试图往目录里io.Copy
tar.gz 是两层嵌套,顺序反了就读出乱码
tar 负责打包(合并多个文件流、保留路径结构),gzip 负责压缩(对 tar 流再压一遍)——它们职责分明,不能互换顺序。有人写 tar.NewReader(gzipFile),结果解出来的全是乱码,因为传进去的是未解压的二进制流。
立即学习“go语言免费学习笔记(深入)”;
- 压缩:先
gzip.NewWriter→ 套tar.NewWriter→ 遍历写tar.Header→tw.Write()内容 →tw.Close()→gz.Close() - 解压:先
gzip.NewReader(gzFile)→ 再传给tar.NewReader()→ 逐个读tar.Header→ 按Typeflag判断是tar.TypeDir还是tar.TypeReg -
tar.Header.Size必须准确设置,否则io.Copy会读超或截断

















