package compress import ( "archive/zip" "bytes" "io" "os" "path/filepath" ) // UnzipFromFile 解压压缩文件 // @params dst string 解压后目标路径 // @params src string 压缩文件目标路径 func UnzipFromFile(dst, src string) error { // 打开压缩文件 zr, err := zip.OpenReader(filepath.Clean(src)) if err != nil { return err } defer func() { _ = zr.Close() }() // 解压 return Unzip(dst, &zr.Reader) } // UnzipFromBytes 解压压缩字节流 // @params dst string 解压后目标路径 // @params src []byte 压缩字节流 func UnzipFromBytes(dst string, src []byte) error { // 通过字节流创建zip的Reader对象 zr, err := zip.NewReader(bytes.NewReader(src), int64(len(src))) if err != nil { return err } // 解压 return Unzip(dst, zr) } // Unzip 解压压缩文件 // @params dst string 解压后的目标路径 // @params src *zip.Reader 压缩文件可读流 func Unzip(dst string, src *zip.Reader) error { // 强制转换一遍目录 dst = filepath.Clean(dst) // 遍历压缩文件 for _, file := range src.File { // 在闭包中完成以下操作可以及时释放文件句柄 err := func() error { // 跳过文件夹 if file.Mode().IsDir() { return nil } // 配置输出目标路径 filename := filepath.Join(dst, file.Name) // 创建目标路径所在文件夹 e := os.MkdirAll(filepath.Dir(filename), os.ModeDir) if e != nil { return e } // 打开这个压缩文件 zfr, e := file.Open() if e != nil { return e } defer func() { _ = zfr.Close() }() // 创建目标文件 fw, e := os.Create(filename) if e != nil { return e } defer func() { _ = fw.Close() }() // 执行拷贝 _, e = io.Copy(fw, zfr) if e != nil { return e } // 拷贝成功 return nil }() // 是否发生异常 if err != nil { return err } } // 解压完成 return nil }