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 }