压缩解压v2

package zipv2

import (
	"bytes"
	"errors"
	f "github.com/cilidm/toolbox/file"
	"github.com/mzky/zip"
	"io"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
)

func IsZip(zipPath string) bool {
	f, err := os.Open(zipPath)
	if err != nil {
		return false
	}
	defer f.Close()

	buf := make([]byte, 4)
	if n, err := f.Read(buf); err != nil || n < 4 {
		return false
	}

	return bytes.Equal(buf, []byte("PK\x03\x04"))
}

// FileIsExist 判断文件夹或文件是否存在, true为存在
func FileIsExist(fp string) bool {
	_, err := os.Stat(fp)
	return err == nil || os.IsExist(err)
}

// IsFile 判断是文件还是目录
func IsFile(fp string) bool {
	fi, e := os.Stat(fp)
	if e != nil {
		return false
	}
	return !fi.IsDir()
}

// TrimValueFromArray 去除数组中指定元素
func TrimValueFromArray(strArray []string, trimValue string) []string {
	newArray := make([]string, 0)
	for _, v := range strArray {
		if strings.TrimSpace(trimValue) != strings.TrimSpace(v) {
			newArray = append(newArray, strings.TrimSpace(v))
		}
	}

	return newArray
}

// Zip password值可以为空""
func Zip(filePath, zipPath, password string) error {
	dirPath, _ := path.Split(zipPath)
	err := f.IsNotExistMkDir(dirPath)
	if err != nil {
		return err
	}
	fz, err := os.Create(zipPath)
	if err != nil {
		return err
	}
	defer fz.Close()
	zw := zip.NewWriter(fz)
	defer zw.Close()
	filepath.Walk(filePath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if filePath == path {
			return nil
		}
		if !strings.HasSuffix(filePath, "/") {
			filePath = filePath + "/"
		}
		if runtime.GOOS == "windows" {
			filePath = strings.ReplaceAll(filePath, "\\", "/")
			path = strings.ReplaceAll(path, "\\", "/")
		}
		fileName := strings.ReplaceAll(path, filePath, "")
		if info.IsDir(){
			fileName += "/"
		}
		// 写入文件的头信息
		var w io.Writer
		var errB error
		if password != "" {
			w, errB = zw.Encrypt(fileName, password, zip.AES256Encryption)
		} else {
			w, errB = zw.Create(fileName)
		}
		if errB != nil {
			return errB
		}

		if !info.IsDir() {
			fr, err := os.Open(path)
			if err != nil {
				return err
			}
			defer fr.Close()
			_, err = io.Copy(w, fr)
		}
		return nil
	})
	return zw.Flush()
}

// UnZip password值可以为空""
// 当decompressPath值为"./"时,解压到相对路径
func UnZip(zipPath, password, decompressPath string) error {
	if !FileIsExist(zipPath) {
		return errors.New("找不到压缩文件")
	}
	if !IsZip(zipPath) {
		return errors.New("压缩文件格式不正确或已损坏")
	}
	r, err := zip.OpenReader(zipPath)
	if err != nil {
		return err
	}
	defer r.Close()

	for _, fi := range r.File {
		if password != "" {
			if fi.IsEncrypted() {
				fi.SetPassword(password)
			} else {
				return errors.New("must be encrypted")
			}
		}
		fp := path.Join(decompressPath, fi.Name)
		if fi.FileInfo().IsDir(){
			err = f.IsNotExistMkDir(fp)
			if err != nil {
				return err
			}
			continue
		}
		_ = os.MkdirAll(path.Dir(fp), os.ModePerm)
		w, errA := os.Create(fp)
		if errA != nil {
			return errors.New("无法创建解压文件")
		}
		fr, errB := fi.Open()
		if errB != nil {
			return errors.New("解压密码不正确")
		}
		if _, errC := io.Copy(w, fr); errC != nil {
			return errC
		}
		fr.Close()
		w.Close()
	}
	return nil
}

最后更新于