From 2be9bb970bbe39ce16316b1eca725f7b6556e596 Mon Sep 17 00:00:00 2001 From: John Guo Date: Sun, 9 Oct 2022 19:19:10 +0800 Subject: [PATCH] add function `ZipPathContent` for package `gcompress` (#2179) add function ZipPathContent for package gcompress --- encoding/gcompress/gcompress_gzip.go | 23 ++-- .../gcompress/gcompress_z_unit_zip_test.go | 33 +++++ encoding/gcompress/gcompress_zip.go | 115 ++++++++++-------- encoding/gcompress/testdata/zip/path2/2.txt | 2 +- 4 files changed, 111 insertions(+), 62 deletions(-) diff --git a/encoding/gcompress/gcompress_gzip.go b/encoding/gcompress/gcompress_gzip.go index f748cbb98..40464f925 100644 --- a/encoding/gcompress/gcompress_gzip.go +++ b/encoding/gcompress/gcompress_gzip.go @@ -47,25 +47,25 @@ func Gzip(data []byte, level ...int) ([]byte, error) { } // GzipFile compresses the file `src` to `dst` using gzip algorithm. -func GzipFile(src, dst string, level ...int) (err error) { - dstFile, err := gfile.Create(dst) +func GzipFile(srcFilePath, dstFilePath string, level ...int) (err error) { + dstFile, err := gfile.Create(dstFilePath) if err != nil { return err } defer dstFile.Close() - return GzipPathWriter(src, dstFile) + return GzipPathWriter(srcFilePath, dstFile, level...) } -// GzipPathWriter compresses `path` to `writer` using gzip compressing algorithm. +// GzipPathWriter compresses `filePath` to `writer` using gzip compressing algorithm. // // Note that the parameter `path` can be either a directory or a file. -func GzipPathWriter(path string, writer io.Writer, level ...int) error { +func GzipPathWriter(filePath string, writer io.Writer, level ...int) error { var ( gzipWriter *gzip.Writer err error ) - srcFile, err := gfile.Open(path) + srcFile, err := gfile.Open(filePath) if err != nil { return err } @@ -74,8 +74,7 @@ func GzipPathWriter(path string, writer io.Writer, level ...int) error { if len(level) > 0 { gzipWriter, err = gzip.NewWriterLevel(writer, level[0]) if err != nil { - err = gerror.Wrap(err, `gzip.NewWriterLevel failed`) - return err + return gerror.Wrap(err, `gzip.NewWriterLevel failed`) } } else { gzipWriter = gzip.NewWriter(writer) @@ -108,14 +107,14 @@ func UnGzip(data []byte) ([]byte, error) { return buf.Bytes(), nil } -// UnGzipFile decompresses file `src` to `dst` using gzip algorithm. -func UnGzipFile(src, dst string) error { - srcFile, err := gfile.Open(src) +// UnGzipFile decompresses srcFilePath `src` to `dst` using gzip algorithm. +func UnGzipFile(srcFilePath, dstFilePath string) error { + srcFile, err := gfile.Open(srcFilePath) if err != nil { return err } defer srcFile.Close() - dstFile, err := gfile.Create(dst) + dstFile, err := gfile.Create(dstFilePath) if err != nil { return err } diff --git a/encoding/gcompress/gcompress_z_unit_zip_test.go b/encoding/gcompress/gcompress_z_unit_zip_test.go index 3d8f51cc4..568b10d56 100644 --- a/encoding/gcompress/gcompress_z_unit_zip_test.go +++ b/encoding/gcompress/gcompress_z_unit_zip_test.go @@ -215,3 +215,36 @@ func Test_ZipPathWriter(t *testing.T) { ) }) } + +func Test_ZipPathContent(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + srcPath = gtest.DataPath("zip") + srcPath1 = gtest.DataPath("zip", "path1") + srcPath2 = gtest.DataPath("zip", "path2") + ) + pwd := gfile.Pwd() + err := gfile.Chdir(srcPath) + defer gfile.Chdir(pwd) + t.AssertNil(err) + + tempDirPath := gfile.Temp(gtime.TimestampNanoStr()) + err = gfile.Mkdir(tempDirPath) + t.AssertNil(err) + + zipContent, err := gcompress.ZipPathContent(srcPath1 + ", " + srcPath2) + t.AssertGT(len(zipContent), 0) + err = gcompress.UnZipContent(zipContent, tempDirPath) + t.AssertNil(err) + defer gfile.Remove(tempDirPath) + + t.Assert( + gfile.GetContents(gfile.Join(tempDirPath, "path1", "1.txt")), + gfile.GetContents(gfile.Join(srcPath, "path1", "1.txt")), + ) + t.Assert( + gfile.GetContents(gfile.Join(tempDirPath, "path2", "2.txt")), + gfile.GetContents(gfile.Join(srcPath, "path2", "2.txt")), + ) + }) +} diff --git a/encoding/gcompress/gcompress_zip.go b/encoding/gcompress/gcompress_zip.go index cdeae621c..1d2290c08 100644 --- a/encoding/gcompress/gcompress_zip.go +++ b/encoding/gcompress/gcompress_zip.go @@ -21,38 +21,38 @@ import ( "github.com/gogf/gf/v2/text/gstr" ) -// ZipPath compresses `paths` to `dest` using zip compressing algorithm. -// The unnecessary parameter `prefix` indicates the path prefix for zip file. +// ZipPath compresses `fileOrFolderPaths` to `dstFilePath` using zip compressing algorithm. // -// Note that the parameter `paths` can be either a directory or a file, which +// The parameter `paths` can be either a directory or a file, which // supports multiple paths join with ','. -func ZipPath(paths, dest string, prefix ...string) error { - writer, err := os.Create(dest) +// The unnecessary parameter `prefix` indicates the path prefix for zip file. +func ZipPath(fileOrFolderPaths, dstFilePath string, prefix ...string) error { + writer, err := os.Create(dstFilePath) if err != nil { - err = gerror.Wrapf(err, `os.Create failed for name "%s"`, dest) + err = gerror.Wrapf(err, `os.Create failed for name "%s"`, dstFilePath) return err } defer writer.Close() zipWriter := zip.NewWriter(writer) defer zipWriter.Close() - for _, path := range strings.Split(paths, ",") { + for _, path := range strings.Split(fileOrFolderPaths, ",") { path = strings.TrimSpace(path) - if err = doZipPathWriter(path, gfile.RealPath(dest), zipWriter, prefix...); err != nil { + if err = doZipPathWriter(path, gfile.RealPath(dstFilePath), zipWriter, prefix...); err != nil { return err } } return nil } -// ZipPathWriter compresses `paths` to `writer` using zip compressing algorithm. -// The unnecessary parameter `prefix` indicates the path prefix for zip file. +// ZipPathWriter compresses `fileOrFolderPaths` to `writer` using zip compressing algorithm. // -// Note that the parameter `paths` can be either a directory or a file, which +// Note that the parameter `fileOrFolderPaths` can be either a directory or a file, which // supports multiple paths join with ','. -func ZipPathWriter(paths string, writer io.Writer, prefix ...string) error { +// The unnecessary parameter `prefix` indicates the path prefix for zip file. +func ZipPathWriter(fileOrFolderPaths string, writer io.Writer, prefix ...string) error { zipWriter := zip.NewWriter(writer) defer zipWriter.Close() - for _, path := range strings.Split(paths, ",") { + for _, path := range strings.Split(fileOrFolderPaths, ",") { path = strings.TrimSpace(path) if err := doZipPathWriter(path, "", zipWriter, prefix...); err != nil { return err @@ -61,39 +61,56 @@ func ZipPathWriter(paths string, writer io.Writer, prefix ...string) error { return nil } -// doZipPathWriter compresses the file of given `path` and writes the content to `zipWriter`. +// ZipPathContent compresses `fileOrFolderPaths` to []byte using zip compressing algorithm. +// +// Note that the parameter `fileOrFolderPaths` can be either a directory or a file, which +// supports multiple paths join with ','. +// The unnecessary parameter `prefix` indicates the path prefix for zip file. +func ZipPathContent(fileOrFolderPaths string, prefix ...string) ([]byte, error) { + var ( + err error + buffer = bytes.NewBuffer(nil) + ) + if err = ZipPathWriter(fileOrFolderPaths, buffer, prefix...); err != nil { + return nil, err + } + return buffer.Bytes(), nil +} + +// doZipPathWriter compresses given `fileOrFolderPaths` and writes the content to `zipWriter`. +// +// The parameter `fileOrFolderPath` can be either a single file or folder path. // The parameter `exclude` specifies the exclusive file path that is not compressed to `zipWriter`, // commonly the destination zip file path. // The unnecessary parameter `prefix` indicates the path prefix for zip file. -func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix ...string) error { +func doZipPathWriter(fileOrFolderPath string, exclude string, zipWriter *zip.Writer, prefix ...string) error { var ( err error files []string ) - path, err = gfile.Search(path) + fileOrFolderPath, err = gfile.Search(fileOrFolderPath) if err != nil { return err } - if gfile.IsDir(path) { - files, err = gfile.ScanDir(path, "*", true) + if gfile.IsDir(fileOrFolderPath) { + files, err = gfile.ScanDir(fileOrFolderPath, "*", true) if err != nil { return err } } else { - files = []string{path} + files = []string{fileOrFolderPath} } headerPrefix := "" if len(prefix) > 0 && prefix[0] != "" { headerPrefix = prefix[0] } headerPrefix = strings.TrimRight(headerPrefix, "\\/") - if gfile.IsDir(path) { + if gfile.IsDir(fileOrFolderPath) { if len(headerPrefix) > 0 { headerPrefix += "/" } else { - headerPrefix = gfile.Basename(path) + headerPrefix = gfile.Basename(fileOrFolderPath) } - } headerPrefix = strings.Replace(headerPrefix, "//", "/", -1) for _, file := range files { @@ -101,7 +118,7 @@ func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix intlog.Printf(context.TODO(), `exclude file path: %s`, file) continue } - dir := gfile.Dir(file[len(path):]) + dir := gfile.Dir(file[len(fileOrFolderPath):]) if dir == "." { dir = "" } @@ -112,41 +129,41 @@ func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix return nil } -// UnZipFile decompresses `archive` to `dest` using zip compressing algorithm. -// The optional parameter `path` specifies the unzipped path of `archive`, -// which can be used to specify part of the archive file to unzip. +// UnZipFile decompresses `archive` to `dstFolderPath` using zip compressing algorithm. // -// Note that the parameter `dest` should be a directory. -func UnZipFile(archive, dest string, path ...string) error { - readerCloser, err := zip.OpenReader(archive) +// The parameter `dstFolderPath` should be a directory. +// The optional parameter `zippedPrefix` specifies the unzipped path of `zippedFilePath`, +// which can be used to specify part of the archive file to unzip. +func UnZipFile(zippedFilePath, dstFolderPath string, zippedPrefix ...string) error { + readerCloser, err := zip.OpenReader(zippedFilePath) if err != nil { - err = gerror.Wrapf(err, `zip.OpenReader failed for name "%s"`, dest) + err = gerror.Wrapf(err, `zip.OpenReader failed for name "%s"`, dstFolderPath) return err } defer readerCloser.Close() - return unZipFileWithReader(&readerCloser.Reader, dest, path...) + return unZipFileWithReader(&readerCloser.Reader, dstFolderPath, zippedPrefix...) } -// UnZipContent decompresses `data` to `dest` using zip compressing algorithm. -// The parameter `path` specifies the unzipped path of `archive`, -// which can be used to specify part of the archive file to unzip. +// UnZipContent decompresses `zippedContent` to `dstFolderPath` using zip compressing algorithm. // -// Note that the parameter `dest` should be a directory. -func UnZipContent(data []byte, dest string, path ...string) error { - reader, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) +// The parameter `dstFolderPath` should be a directory. +// The parameter `zippedPrefix` specifies the unzipped path of `zippedContent`, +// which can be used to specify part of the archive file to unzip. +func UnZipContent(zippedContent []byte, dstFolderPath string, zippedPrefix ...string) error { + reader, err := zip.NewReader(bytes.NewReader(zippedContent), int64(len(zippedContent))) if err != nil { err = gerror.Wrapf(err, `zip.NewReader failed`) return err } - return unZipFileWithReader(reader, dest, path...) + return unZipFileWithReader(reader, dstFolderPath, zippedPrefix...) } -func unZipFileWithReader(reader *zip.Reader, dest string, path ...string) error { +func unZipFileWithReader(reader *zip.Reader, dstFolderPath string, zippedPrefix ...string) error { prefix := "" - if len(path) > 0 { - prefix = gstr.Replace(path[0], `\`, `/`) + if len(zippedPrefix) > 0 { + prefix = gstr.Replace(zippedPrefix[0], `\`, `/`) } - if err := os.MkdirAll(dest, 0755); err != nil { + if err := os.MkdirAll(dstFolderPath, 0755); err != nil { return err } var ( @@ -163,7 +180,7 @@ func unZipFileWithReader(reader *zip.Reader, dest string, path ...string) error } name = name[len(prefix):] } - dstPath = filepath.Join(dest, name) + dstPath = filepath.Join(dstFolderPath, name) if file.FileInfo().IsDir() { _ = os.MkdirAll(dstPath, file.Mode()) continue @@ -206,19 +223,19 @@ func doCopyForUnZipFileWithReader(file *zip.File, fileReader io.ReadCloser, dstP return nil } -// zipFile compresses the file of given `path` and writes the content to `zw`. +// zipFile compresses the file of given `filePath` and writes the content to `zw`. // The parameter `prefix` indicates the path prefix for zip file. -func zipFile(path string, prefix string, zw *zip.Writer) error { - file, err := os.Open(path) +func zipFile(filePath string, prefix string, zw *zip.Writer) error { + file, err := os.Open(filePath) if err != nil { - err = gerror.Wrapf(err, `os.Open failed for name "%s"`, path) + err = gerror.Wrapf(err, `os.Open failed for name "%s"`, filePath) return nil } defer file.Close() info, err := file.Stat() if err != nil { - err = gerror.Wrapf(err, `file.Stat failed for name "%s"`, path) + err = gerror.Wrapf(err, `file.Stat failed for name "%s"`, filePath) return err } @@ -240,7 +257,7 @@ func zipFile(path string, prefix string, zw *zip.Writer) error { } if !info.IsDir() { if _, err = io.Copy(writer, file); err != nil { - err = gerror.Wrapf(err, `io.Copy failed from "%s" to "%s"`, path, header.Name) + err = gerror.Wrapf(err, `io.Copy failed from "%s" to "%s"`, filePath, header.Name) return err } } diff --git a/encoding/gcompress/testdata/zip/path2/2.txt b/encoding/gcompress/testdata/zip/path2/2.txt index f51884841..4acbec689 100644 --- a/encoding/gcompress/testdata/zip/path2/2.txt +++ b/encoding/gcompress/testdata/zip/path2/2.txt @@ -1 +1 @@ -This is an another test file for zip compression purpose. \ No newline at end of file +This is another test file for zip compression purpose. \ No newline at end of file