- 运行目录定位、路径存在性、带进度回调下载、Zip 打包/解压(兼容 GBK 中文文件名) - 附单元测试、examples/filex 例程与包 README
121 lines
2.5 KiB
Go
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
|
|
}
|