Files
leanote/app/lea/archive/zip.go

200 lines
4.2 KiB
Go
Raw Normal View History

2014-11-09 16:24:19 +08:00
package archive
import (
2015-11-13 17:58:41 +08:00
"archive/zip"
"fmt"
"io"
"os"
"path"
2014-11-09 16:24:19 +08:00
"strings"
2016-10-27 16:37:12 +08:00
"github.com/leanote/leanote/app/lea"
2014-11-09 16:24:19 +08:00
)
// main functions shows how to TarGz a directory/file and
// UnTarGz a file
// Gzip and tar from source directory or file to destination file
// you need check file exist before you call this function
func Zip(srcDirPath string, destFilePath string) (ok bool) {
2015-11-13 17:58:41 +08:00
defer func() { //必须要先声明defer否则不能捕获到panic异常
2014-11-09 16:24:19 +08:00
if err := recover(); err != nil {
ok = false
}
}()
2015-11-13 17:58:41 +08:00
fw, err := os.Create(destFilePath)
if err != nil {
panic(err)
}
defer fw.Close()
// Tar writer
tw := zip.NewWriter(fw)
defer tw.Close()
// Check if it's a file or a directory
f, err := os.Open(srcDirPath)
if err != nil {
panic(err)
}
fi, err := f.Stat()
if err != nil {
panic(err)
}
if fi.IsDir() {
// handle source directory
// fmt.Println("Cerating tar.gz from directory...")
zipDir(srcDirPath, path.Base(srcDirPath), tw)
} else {
// handle file directly
// fmt.Println("Cerating tar.gz from " + fi.Name() + "...")
zipFile(srcDirPath, fi.Name(), tw, fi)
}
ok = true
return
2014-11-09 16:24:19 +08:00
}
// Deal with directories
// if find files, handle them with zipFile
// Every recurrence append the base path to the recPath
// recPath is the path inside of tar.gz
func zipDir(srcDirPath string, recPath string, tw *zip.Writer) {
2015-11-13 17:58:41 +08:00
// Open source diretory
dir, err := os.Open(srcDirPath)
if err != nil {
panic(err)
}
defer dir.Close()
// Get file info slice
fis, err := dir.Readdir(0)
if err != nil {
panic(err)
}
for _, fi := range fis {
// Append path
curPath := srcDirPath + "/" + fi.Name()
// Check it is directory or file
if fi.IsDir() {
// Directory
// (Directory won't add unitl all subfiles are added)
// fmt.Printf("Adding path...%s\n", curPath)
zipDir(curPath, recPath+"/"+fi.Name(), tw)
} else {
// File
// fmt.Printf("Adding file...%s\n", curPath)
}
zipFile(curPath, recPath+"/"+fi.Name(), tw, fi)
}
2014-11-09 16:24:19 +08:00
}
// Deal with files
func zipFile(srcFile string, recPath string, tw *zip.Writer, fi os.FileInfo) {
2015-11-13 17:58:41 +08:00
if fi.IsDir() {
// fmt.Println("??")
// Create tar header
/*
fh, err := zip.FileInfoHeader(fi)
if err != nil {
panic(err)
}
fh.Name = recPath // + "/"
err = tw.WriteHeader(hdr)
tw.Create(recPath)
*/
} else {
// File reader
fr, err := os.Open(srcFile)
if err != nil {
panic(err)
}
defer fr.Close()
// Write hander
w, err2 := tw.Create(recPath)
if err2 != nil {
panic(err)
}
// Write file data
_, err = io.Copy(w, fr)
if err != nil {
panic(err)
}
}
2014-11-09 16:24:19 +08:00
}
// Ungzip and untar from source file to destination directory
// you need check file exist before you call this function
func Unzip(srcFilePath string, destDirPath string) (ok bool, msg string) {
ok = false
msg = ""
2015-11-13 17:58:41 +08:00
defer func() { //必须要先声明defer否则不能捕获到panic异常
2014-11-09 16:24:19 +08:00
if err := recover(); err != nil {
msg = fmt.Sprintf("%v", err)
ok = false
}
}()
2015-11-13 17:58:41 +08:00
2014-11-09 16:24:19 +08:00
os.Mkdir(destDirPath, os.ModePerm)
2015-11-13 17:58:41 +08:00
r, err := zip.OpenReader(srcFilePath)
2014-11-09 16:24:19 +08:00
if err != nil {
panic(err)
}
2015-11-13 17:58:41 +08:00
defer r.Close()
2014-11-09 16:24:19 +08:00
for _, f := range r.File {
2016-10-27 16:37:12 +08:00
// fmt.Println("FileName : ", f.Name); // j/aaa.zip
2015-11-13 17:58:41 +08:00
rc, err := f.Open()
if err != nil {
2014-11-09 16:24:19 +08:00
panic(err)
}
2015-11-13 17:58:41 +08:00
2016-10-27 16:37:12 +08:00
// 包含恶意目录
if strings.Contains(f.Name, "../") {
lea.LogW("恶意文件", f.Name);
continue
}
2014-11-09 16:24:19 +08:00
// 把首文件夹去掉, 即j去掉, 分离出文件夹和文件名
paths := strings.Split(f.Name, "/")
prePath := ""
filename := ""
l := len(paths)
2015-11-13 17:58:41 +08:00
// fmt.Println(l)
2014-11-09 16:24:19 +08:00
if l > 1 {
// 去掉第1个文件夹
if l == 2 {
filename = paths[1]
} else {
filename = paths[l-1]
prePath = strings.Join(paths[1:l-1], "/")
}
} else {
filename = f.Name
}
2015-11-13 17:58:41 +08:00
// fmt.Println(prePath)
2014-11-09 16:24:19 +08:00
// 相对于目标文件件下的路径
2015-11-13 17:58:41 +08:00
destPath := destDirPath + "/" + filename
2014-11-09 16:24:19 +08:00
if prePath != "" {
2015-11-13 17:58:41 +08:00
os.MkdirAll(destDirPath+"/"+prePath, os.ModePerm)
2014-11-09 16:24:19 +08:00
destPath = destDirPath + "/" + prePath + "/" + filename
}
2015-11-13 17:58:41 +08:00
// Write data to file
// fmt.Println(destPath)
fw, _ := os.Create(destPath)
if err != nil {
panic(err)
}
_, err = io.Copy(fw, rc)
if err != nil {
panic(err)
}
2014-11-09 16:24:19 +08:00
}
2015-11-13 17:58:41 +08:00
2014-11-09 16:24:19 +08:00
ok = true
return
2015-11-13 17:58:41 +08:00
}