mindoc/utils/ziptil/ziptil.go

180 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package ziptil
import (
"archive/zip"
"errors"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/lifei6671/mindoc/utils/filetil"
)
//解压zip文件
//@param zipFile 需要解压的zip文件
//@param dest 需要解压到的目录
//@return err 返回错误
func Unzip(zipFile, dest string) (err error) {
dest = strings.TrimSuffix(dest, "/") + "/"
// 打开一个zip格式文件
r, err := zip.OpenReader(zipFile)
if err != nil {
return err
}
defer r.Close()
// 迭代压缩文件中的文件,打印出文件中的内容
for _, f := range r.File {
if !f.FileInfo().IsDir() { //非目录且不包含__MACOSX
if folder := dest + filepath.Dir(f.Name); !strings.Contains(folder, "__MACOSX") {
os.MkdirAll(folder, 0777)
if fcreate, err := os.Create(dest + strings.TrimPrefix(f.Name, "./")); err == nil {
if rc, err := f.Open(); err == nil {
io.Copy(fcreate, rc)
rc.Close() //不要用defer来关闭如果文件太多的话会报too many open files 的错误
fcreate.Close()
} else {
fcreate.Close()
return err
}
} else {
return err
}
}
}
}
return nil
}
//压缩指定文件或文件夹
//@param dest 压缩后的zip文件目标如/usr/local/hello.zip
//@param filepath 需要压缩的文件或者文件夹
//@return err 错误。如果返回错误则会删除dest文件
func Zip(dest string, filepath ...string) (err error) {
if len(filepath) == 0 {
return errors.New("lack of file")
}
//创建文件
fzip, err := os.Create(dest)
if err != nil {
return err
}
defer fzip.Close()
var filelist []filetil.FileList
for _, file := range filepath {
if info, err := os.Stat(file); err == nil {
if info.IsDir() { //目录,则扫描文件
if f, _ := filetil.ScanFiles(file); len(f) > 0 {
filelist = append(filelist, f...)
}
} else { //文件
filelist = append(filelist, filetil.FileList{
IsDir: false,
Name: info.Name(),
Path: file,
})
}
} else {
return err
}
}
w := zip.NewWriter(fzip)
defer w.Close()
for _, file := range filelist {
if !file.IsDir {
if fw, err := w.Create(strings.TrimLeft(file.Path, "./")); err != nil {
return err
} else {
if fileContent, err := ioutil.ReadFile(file.Path); err != nil {
return err
} else {
if _, err = fw.Write(fileContent); err != nil {
return err
}
}
}
}
}
return
}
func Compress(dst string,src string) (err error) {
d, _ := os.Create(dst)
defer d.Close()
w := zip.NewWriter(d)
defer w.Close()
src = strings.Replace(src,"\\","/",-1)
f, err := os.Open(src)
if err != nil {
return err
}
//prefix := src[strings.LastIndex(src,"/"):]
err = compress(f, "", w)
if err != nil {
return err
}
return nil
}
func compress(file *os.File, prefix string, zw *zip.Writer) error {
info, err := file.Stat()
if err != nil {
return err
}
if info.IsDir() {
if prefix != "" {
prefix = prefix + "/" + info.Name()
}else{
prefix = info.Name()
}
fileInfos, err := file.Readdir(-1)
if err != nil {
return err
}
for _, fi := range fileInfos {
f, err := os.Open(file.Name() + "/" + fi.Name())
if err != nil {
return err
}
err = compress(f, prefix, zw)
if err != nil {
return err
}
}
} else {
header, err := zip.FileInfoHeader(info)
if prefix != "" {
header.Name = prefix + "/" + header.Name
}
if err != nil {
return err
}
writer, err := zw.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(writer, file)
file.Close()
if err != nil {
return err
}
}
return nil
}