123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- package utils
- import (
- "archive/zip"
- "fmt"
- "io"
- "io/fs"
- "log"
- "os"
- "path"
- "path/filepath"
- "strings"
- )
- func Zip(zipPath string, paths ...string) error {
- // Create zip file and it's parent dir.
- if err := os.MkdirAll(filepath.Dir(zipPath), os.ModePerm); err != nil {
- return err
- }
- archive, err := os.Create(zipPath)
- if err != nil {
- return err
- }
- defer archive.Close()
- // New zip writer.
- zipWriter := zip.NewWriter(archive)
- defer zipWriter.Close()
- // Traverse the file or directory.
- for _, rootPath := range paths {
- // Remove the trailing path separator if path is a directory.
- rootPath = strings.TrimSuffix(rootPath, string(os.PathSeparator))
- // Visit all the files or directories in the tree.
- err = filepath.Walk(rootPath, walkFunc(rootPath, zipWriter))
- if err != nil {
- return err
- }
- }
- return nil
- }
- func walkFunc(rootPath string, zipWriter *zip.Writer) filepath.WalkFunc {
- return func(path string, info fs.FileInfo, err error) error {
- if err != nil {
- return err
- }
- // If a file is a symbolic link it will be skipped.
- if info.Mode()&os.ModeSymlink != 0 {
- return nil
- }
- // Create a local file header.
- header, err := zip.FileInfoHeader(info)
- if err != nil {
- return err
- }
- // Set compression method.
- header.Method = zip.Deflate
- // Set relative path of a file as the header name.
- header.Name, err = filepath.Rel(rootPath, path)
- if err != nil {
- return err
- }
- if info.IsDir() {
- header.Name += string(os.PathSeparator)
- }
- // Create writer for the file header and save content of the file.
- headerWriter, err := zipWriter.CreateHeader(header)
- if err != nil {
- return err
- }
- if info.IsDir() {
- return nil
- }
- fmt.Println(header.Name)
- f, err := os.Open(path)
- if err != nil {
- return err
- }
- defer f.Close()
- _, err = io.Copy(headerWriter, f)
- return err
- }
- }
- func Unzip(zipPath, dstDir string, cb func(per1000 int)) error {
- // open zip file
- reader, err := zip.OpenReader(zipPath)
- if err != nil {
- return err
- }
- defer reader.Close()
- total := len(reader.File)
- for index, file := range reader.File {
- per1000 := int(float32(index+1) / float32(total) * 1000)
- // log.Println("unzip=>", file.Name, index, "/", len(reader.File))
- log.Println("unzip=>", file.Name)
- if cb != nil {
- cb(per1000)
- }
- if err := unzipFile(file, dstDir); err != nil {
- return err
- }
- }
- return nil
- }
- func unzipFile(file *zip.File, dstDir string) error {
- // create the directory of file
- filePath := path.Join(dstDir, file.Name)
- if file.FileInfo().IsDir() {
- if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
- return err
- }
- return nil
- }
- if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
- return err
- }
- // open the file
- rc, err := file.Open()
- if err != nil {
- return err
- }
- defer rc.Close()
- // create the file
- w, err := os.Create(filePath)
- if err != nil {
- return err
- }
- defer w.Close()
- // save the decompressed file content
- _, err = io.Copy(w, rc)
- return err
- }
|