gitee.com/h79/goutils@v1.22.10/common/archive/zip.go (about)

     1  package archive
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"gitee.com/h79/goutils/common/file"
     7  	fileconfig "gitee.com/h79/goutils/common/file/config"
     8  	"io"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  )
    13  
    14  func IsZip(zipPath string) bool {
    15  	f, err := os.Open(zipPath)
    16  	if err != nil {
    17  		return false
    18  	}
    19  	defer f.Close()
    20  
    21  	buf := make([]byte, 4)
    22  	if n, err := f.Read(buf); err != nil || n < 4 {
    23  		return false
    24  	}
    25  	return bytes.Equal(buf, []byte("PK\x03\x04"))
    26  }
    27  
    28  func UnZipFile(archive, target string, stream ...fileconfig.WriteStream) error {
    29  	reader, err := zip.OpenReader(archive)
    30  	if err != nil {
    31  		return err
    32  	}
    33  	defer reader.Close()
    34  	for i := range reader.File {
    35  		f := reader.File[i]
    36  		path := filepath.Join(target, f.Name)
    37  		if f.FileInfo().IsDir() {
    38  			if err := os.MkdirAll(path, f.Mode()); err != nil {
    39  				return err
    40  			}
    41  			continue
    42  		}
    43  		fileReader, err := f.Open()
    44  		if err != nil {
    45  			return err
    46  		}
    47  		targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
    48  		if err != nil {
    49  			_ = fileReader.Close()
    50  			return err
    51  		}
    52  		if _, err := io.Copy(targetFile, fileReader); err != nil {
    53  			_ = targetFile.Close()
    54  			_ = fileReader.Close()
    55  			return err
    56  		}
    57  		for j := range stream {
    58  			stream[j].OnWriter(targetFile)
    59  		}
    60  		_ = targetFile.Close()
    61  		_ = fileReader.Close()
    62  	}
    63  	return nil
    64  }
    65  
    66  func ZipFile(srcPath, destPath string, stream ...fileconfig.ReaderStream) error {
    67  	zipFile, err := os.Create(destPath)
    68  	if err != nil {
    69  		return err
    70  	}
    71  	defer zipFile.Close()
    72  
    73  	return ZipWrite(zipFile, srcPath, stream...)
    74  }
    75  
    76  func ZipWrite(writer io.Writer, srcPath string, stream ...fileconfig.ReaderStream) error {
    77  
    78  	archive := zip.NewWriter(writer)
    79  	defer archive.Close()
    80  
    81  	depth := file.WithMaxDepth()
    82  	return file.ReadDir(srcPath, &depth, func(path string, isDir bool, entry os.DirEntry) int {
    83  		info, err := entry.Info()
    84  		if err != nil {
    85  			return -1
    86  		}
    87  		header, err := zip.FileInfoHeader(info)
    88  		if err != nil {
    89  			return -1
    90  		}
    91  		header.Name = strings.TrimPrefix(path, srcPath+`/`)
    92  		if isDir {
    93  			header.Name += `/`
    94  		} else {
    95  			header.Method = zip.Deflate
    96  		}
    97  		w, err := archive.CreateHeader(header)
    98  		if err != nil {
    99  			return -1
   100  		}
   101  		if isDir {
   102  			return 0
   103  		}
   104  		f, err := os.Open(path)
   105  		if err != nil {
   106  			return -2
   107  		}
   108  		defer f.Close()
   109  		if ll, err := io.Copy(w, f); err != nil || ll != info.Size() {
   110  			return -3
   111  		}
   112  		for i := range stream {
   113  			stream[i].OnReader(f)
   114  		}
   115  		return 0
   116  	})
   117  }