Files
zogo/filex/zip.go
T
4566704 c7e8eb14f8 feat(filex): 自 go-hua/common 迁入文件目录工具并独立成包
- 运行目录定位、路径存在性、带进度回调下载、Zip 打包/解压(兼容 GBK 中文文件名)
- 附单元测试、examples/filex 例程与包 README
2026-09-20 12:20:50 +08:00

121 lines
2.5 KiB
Go

package filex
import (
"archive/zip"
"bytes"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"io"
"os"
"path/filepath"
"strings"
)
// Zip 打包成zip文件 可以是目录或单个文件
func Zip(srcFile string, destZip string) error {
// 预防:旧文件无法覆盖
os.RemoveAll(destZip)
//创建zip文件
zipFile, err := os.Create(destZip)
if err != nil {
return err
}
defer zipFile.Close()
//打开zip文件
archive := zip.NewWriter(zipFile)
defer archive.Close()
//遍历目录
filepath.Walk(srcFile, func(path string, info os.FileInfo, err error) error {
//println(path)
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = strings.TrimPrefix(path, filepath.Dir(srcFile)+string(os.PathSeparator))
println(header.Name)
// header.Name = path
if info.IsDir() {
header.Name += "\\"
} else {
header.Method = zip.Deflate
}
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
if !info.IsDir() {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
if err != nil {
return err
}
}
return err
})
return err
}
// Unzip 解压 zip 文件到指定目录(兼容 GBK 编码的中文文件名)
func Unzip(zipFile string, destDir string) error {
zipReader, err := zip.OpenReader(zipFile)
if err != nil {
return err
}
defer zipReader.Close()
for _, f := range zipReader.File {
var decodeName string
if f.Flags == 0 {
//如果标致位是0 则是默认的本地编码 默认为gbk
i := bytes.NewReader([]byte(f.Name))
decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
content, _ := io.ReadAll(decoder)
decodeName = string(content)
} else {
//如果标志为是 1 << 11也就是 2048 则是utf-8编码
decodeName = f.Name
}
fpath := filepath.Join(destDir, decodeName)
if f.FileInfo().IsDir() {
os.MkdirAll(fpath, os.ModePerm)
} else {
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return err
}
inFile, err := f.Open()
if err != nil {
return err
}
defer inFile.Close()
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return err
}
defer outFile.Close()
_, err = io.Copy(outFile, inFile)
if err != nil {
return err
}
}
}
return nil
}