mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 03:07:45 +08:00
fix issue in zip feature for package gcompress; improve package gres
This commit is contained in:
parent
3db83e1159
commit
f7c2a51c9f
@ -1,15 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/encoding/gcompress"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// srcFile could be a single file or a directory
|
||||
func Zip(srcFile string, destZip string) error {
|
||||
zipfile, err := os.Create(destZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipfile.Close()
|
||||
|
||||
archive := zip.NewWriter(zipfile)
|
||||
defer archive.Close()
|
||||
|
||||
filepath.Walk(srcFile, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = strings.TrimPrefix(path, filepath.Dir(srcFile)+"/")
|
||||
// header.Name = path
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(writer, file)
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := gcompress.ZipPath(
|
||||
`/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/test`,
|
||||
`/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/test.zip`,
|
||||
)
|
||||
fmt.Println(err)
|
||||
src := `/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/test`
|
||||
dst := `/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/test.zip`
|
||||
//src := `/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/README.MD`
|
||||
//dst := `/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/README.MD.zip`
|
||||
fmt.Println(gcompress.ZipPath(src, dst))
|
||||
//fmt.Println(Zip(src, dst))
|
||||
}
|
||||
|
@ -24,25 +24,88 @@ func Test_ZipPath(t *testing.T) {
|
||||
dstPath := gdebug.TestDataPath("zip", "zip.zip")
|
||||
|
||||
t.Assert(gfile.Exists(dstPath), false)
|
||||
err := gcompress.ZipPath(srcPath, dstPath)
|
||||
t.Assert(gcompress.ZipPath(srcPath, dstPath), nil)
|
||||
t.Assert(gfile.Exists(dstPath), true)
|
||||
defer gfile.Remove(dstPath)
|
||||
|
||||
// unzip to temporary dir.
|
||||
tempDirPath := gfile.TempDir(gtime.TimestampNanoStr())
|
||||
t.Assert(gfile.Mkdir(tempDirPath), nil)
|
||||
t.Assert(gcompress.UnZipFile(dstPath, tempDirPath), nil)
|
||||
defer gfile.Remove(tempDirPath)
|
||||
|
||||
t.Assert(
|
||||
gfile.GetContents(gfile.Join(tempDirPath, "1.txt")),
|
||||
gfile.GetContents(srcPath),
|
||||
)
|
||||
})
|
||||
// multiple files
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
srcPath1 = gdebug.TestDataPath("zip", "path1", "1.txt")
|
||||
srcPath2 = gdebug.TestDataPath("zip", "path2", "2.txt")
|
||||
dstPath = gfile.TempDir(gtime.TimestampNanoStr(), "zip.zip")
|
||||
)
|
||||
if p := gfile.Dir(dstPath); !gfile.Exists(p) {
|
||||
t.Assert(gfile.Mkdir(p), nil)
|
||||
}
|
||||
|
||||
t.Assert(gfile.Exists(dstPath), false)
|
||||
err := gcompress.ZipPath(srcPath1+","+srcPath2, dstPath)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(gfile.Exists(dstPath), true)
|
||||
defer gfile.Remove(dstPath)
|
||||
|
||||
// unzip to another temporary dir.
|
||||
tempDirPath := gfile.TempDir(gtime.TimestampNanoStr())
|
||||
err = gfile.Mkdir(tempDirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
t.Assert(gfile.Mkdir(tempDirPath), nil)
|
||||
err = gcompress.UnZipFile(dstPath, tempDirPath)
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(tempDirPath)
|
||||
|
||||
t.Assert(
|
||||
gfile.GetContents(gfile.Join(tempDirPath, "1.txt")),
|
||||
gfile.GetContents(gfile.Join(srcPath, "path1", "1.txt")),
|
||||
gfile.GetContents(srcPath1),
|
||||
)
|
||||
t.Assert(
|
||||
gfile.GetContents(gfile.Join(tempDirPath, "2.txt")),
|
||||
gfile.GetContents(srcPath2),
|
||||
)
|
||||
})
|
||||
// directory
|
||||
// one dir and one file.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
srcPath1 = gdebug.TestDataPath("zip", "path1")
|
||||
srcPath2 = gdebug.TestDataPath("zip", "path2", "2.txt")
|
||||
dstPath = gfile.TempDir(gtime.TimestampNanoStr(), "zip.zip")
|
||||
)
|
||||
if p := gfile.Dir(dstPath); !gfile.Exists(p) {
|
||||
t.Assert(gfile.Mkdir(p), nil)
|
||||
}
|
||||
|
||||
t.Assert(gfile.Exists(dstPath), false)
|
||||
err := gcompress.ZipPath(srcPath1+","+srcPath2, dstPath)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(gfile.Exists(dstPath), true)
|
||||
defer gfile.Remove(dstPath)
|
||||
|
||||
// unzip to another temporary dir.
|
||||
tempDirPath := gfile.TempDir(gtime.TimestampNanoStr())
|
||||
t.Assert(gfile.Mkdir(tempDirPath), nil)
|
||||
err = gcompress.UnZipFile(dstPath, tempDirPath)
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(tempDirPath)
|
||||
|
||||
t.Assert(
|
||||
gfile.GetContents(gfile.Join(tempDirPath, "path1", "1.txt")),
|
||||
gfile.GetContents(gfile.Join(srcPath1, "1.txt")),
|
||||
)
|
||||
t.Assert(
|
||||
gfile.GetContents(gfile.Join(tempDirPath, "2.txt")),
|
||||
gfile.GetContents(srcPath2),
|
||||
)
|
||||
})
|
||||
// directory.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
srcPath := gdebug.TestDataPath("zip")
|
||||
dstPath := gdebug.TestDataPath("zip", "zip.zip")
|
||||
@ -75,13 +138,14 @@ func Test_ZipPath(t *testing.T) {
|
||||
gfile.GetContents(gfile.Join(srcPath, "path2", "2.txt")),
|
||||
)
|
||||
})
|
||||
// multiple paths joined using char ','
|
||||
// multiple directory paths joined using char ','.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
srcPath := gdebug.TestDataPath("zip")
|
||||
srcPath1 := gdebug.TestDataPath("zip", "path1")
|
||||
srcPath2 := gdebug.TestDataPath("zip", "path2")
|
||||
dstPath := gdebug.TestDataPath("zip", "zip.zip")
|
||||
|
||||
var (
|
||||
srcPath = gdebug.TestDataPath("zip")
|
||||
srcPath1 = gdebug.TestDataPath("zip", "path1")
|
||||
srcPath2 = gdebug.TestDataPath("zip", "path2")
|
||||
dstPath = gdebug.TestDataPath("zip", "zip.zip")
|
||||
)
|
||||
pwd := gfile.Pwd()
|
||||
err := gfile.Chdir(srcPath)
|
||||
defer gfile.Chdir(pwd)
|
||||
@ -116,10 +180,11 @@ func Test_ZipPath(t *testing.T) {
|
||||
|
||||
func Test_ZipPathWriter(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
srcPath := gdebug.TestDataPath("zip")
|
||||
srcPath1 := gdebug.TestDataPath("zip", "path1")
|
||||
srcPath2 := gdebug.TestDataPath("zip", "path2")
|
||||
|
||||
var (
|
||||
srcPath = gdebug.TestDataPath("zip")
|
||||
srcPath1 = gdebug.TestDataPath("zip", "path1")
|
||||
srcPath2 = gdebug.TestDataPath("zip", "path2")
|
||||
)
|
||||
pwd := gfile.Pwd()
|
||||
err := gfile.Chdir(srcPath)
|
||||
defer gfile.Chdir(pwd)
|
||||
|
@ -10,16 +10,12 @@ import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/internal/fileinfo"
|
||||
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
)
|
||||
|
||||
// ZipPath compresses <paths> to <dest> using zip compressing algorithm.
|
||||
@ -85,35 +81,29 @@ func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix
|
||||
headerPrefix = prefix[0]
|
||||
}
|
||||
headerPrefix = strings.TrimRight(headerPrefix, "\\/")
|
||||
if len(headerPrefix) > 0 && gfile.IsDir(path) {
|
||||
if gfile.IsDir(path) {
|
||||
if len(headerPrefix) > 0 {
|
||||
headerPrefix += "/"
|
||||
}
|
||||
if headerPrefix == "" {
|
||||
} else {
|
||||
headerPrefix = gfile.Basename(path)
|
||||
}
|
||||
|
||||
}
|
||||
headerPrefix = strings.Replace(headerPrefix, "//", "/", -1)
|
||||
for _, file := range files {
|
||||
if exclude == file {
|
||||
intlog.Printf(`exclude file path: %s`, file)
|
||||
continue
|
||||
}
|
||||
err := zipFile(file, headerPrefix+gfile.Dir(file[len(path):]), zipWriter)
|
||||
dir := gfile.Dir(file[len(path):])
|
||||
if dir == "." {
|
||||
dir = ""
|
||||
}
|
||||
err := zipFile(file, headerPrefix+dir, zipWriter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Add prefix to zip archive.
|
||||
path = headerPrefix
|
||||
for {
|
||||
err := zipFileVirtual(fileinfo.New(gfile.Basename(path), 0, os.ModeDir, time.Now()), path, zipWriter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if path == "/" || !strings.Contains(path, "/") {
|
||||
break
|
||||
}
|
||||
path = gfile.Dir(path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -203,14 +193,23 @@ func zipFile(path string, prefix string, zw *zip.Writer) error {
|
||||
return nil
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := createFileHeader(info, prefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := zw.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -223,23 +222,12 @@ func zipFile(path string, prefix string, zw *zip.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func zipFileVirtual(info os.FileInfo, path string, zw *zip.Writer) error {
|
||||
header, err := createFileHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = path
|
||||
if _, err := zw.CreateHeader(header); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createFileHeader(info os.FileInfo, prefix string) (*zip.FileHeader, error) {
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(prefix) > 0 {
|
||||
prefix = strings.Replace(prefix, `\`, `/`, -1)
|
||||
prefix = strings.TrimRight(prefix, `/`)
|
||||
|
@ -11,9 +11,9 @@ import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/encoding/gcompress"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
|
||||
"github.com/gogf/gf/encoding/gcompress"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
)
|
||||
|
||||
@ -41,7 +41,7 @@ func Pack(srcPaths string, keyPrefix ...string) ([]byte, error) {
|
||||
if len(keyPrefix) > 0 && keyPrefix[0] != "" {
|
||||
headerPrefix = keyPrefix[0]
|
||||
}
|
||||
err := gcompress.ZipPathWriter(srcPaths, buffer, headerPrefix)
|
||||
err := zipPathWriter(srcPaths, buffer, headerPrefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
153
os/gres/gres_func_zip.go
Normal file
153
os/gres/gres_func_zip.go
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright 2020 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gres
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"github.com/gogf/gf/internal/fileinfo"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ZipPathWriter compresses <paths> to <writer> using zip compressing algorithm.
|
||||
// The unnecessary parameter <prefix> indicates the path prefix for zip file.
|
||||
//
|
||||
// Note that the parameter <paths> can be either a directory or a file, which
|
||||
// supports multiple paths join with ','.
|
||||
func zipPathWriter(paths string, writer io.Writer, prefix ...string) error {
|
||||
zipWriter := zip.NewWriter(writer)
|
||||
defer zipWriter.Close()
|
||||
for _, path := range strings.Split(paths, ",") {
|
||||
path = strings.TrimSpace(path)
|
||||
if err := doZipPathWriter(path, "", zipWriter, prefix...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// doZipPathWriter compresses the file of given <path> and writes the content to <zipWriter>.
|
||||
// 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 {
|
||||
var err error
|
||||
var files []string
|
||||
path, err = gfile.Search(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if gfile.IsDir(path) {
|
||||
files, err = gfile.ScanDir(path, "*", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
files = []string{path}
|
||||
}
|
||||
headerPrefix := ""
|
||||
if len(prefix) > 0 && prefix[0] != "" {
|
||||
headerPrefix = prefix[0]
|
||||
}
|
||||
headerPrefix = strings.TrimRight(headerPrefix, "\\/")
|
||||
if len(headerPrefix) > 0 && gfile.IsDir(path) {
|
||||
headerPrefix += "/"
|
||||
}
|
||||
if headerPrefix == "" {
|
||||
headerPrefix = gfile.Basename(path)
|
||||
}
|
||||
headerPrefix = strings.Replace(headerPrefix, "//", "/", -1)
|
||||
for _, file := range files {
|
||||
if exclude == file {
|
||||
intlog.Printf(`exclude file path: %s`, file)
|
||||
continue
|
||||
}
|
||||
err := zipFile(file, headerPrefix+gfile.Dir(file[len(path):]), zipWriter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Add all directories to zip archive.
|
||||
if headerPrefix != "" {
|
||||
var name string
|
||||
path = headerPrefix
|
||||
for {
|
||||
name = gfile.Basename(path)
|
||||
err := zipFileVirtual(
|
||||
fileinfo.New(name, 0, os.ModeDir|os.ModePerm, time.Now()), path, zipWriter,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if path == "/" || !strings.Contains(path, "/") {
|
||||
break
|
||||
}
|
||||
path = gfile.Dir(path)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// zipFile compresses the file of given <path> 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)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer file.Close()
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header, err := createFileHeader(info, prefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
writer, err := zw.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
if _, err = io.Copy(writer, file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func zipFileVirtual(info os.FileInfo, path string, zw *zip.Writer) error {
|
||||
header, err := createFileHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = path
|
||||
if _, err := zw.CreateHeader(header); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createFileHeader(info os.FileInfo, prefix string) (*zip.FileHeader, error) {
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(prefix) > 0 {
|
||||
prefix = strings.Replace(prefix, `\`, `/`, -1)
|
||||
prefix = strings.TrimRight(prefix, `/`)
|
||||
header.Name = prefix + `/` + header.Name
|
||||
}
|
||||
return header, nil
|
||||
}
|
@ -35,9 +35,10 @@ func Test_Pack(t *testing.T) {
|
||||
t.Assert(err, nil)
|
||||
|
||||
r := gres.New()
|
||||
|
||||
err = r.Add(string(data))
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Contains("files"), true)
|
||||
t.Assert(r.Contains("files/"), true)
|
||||
})
|
||||
}
|
||||
|
||||
|
2
os/gres/testdata/data/data.go
vendored
2
os/gres/testdata/data/data.go
vendored
File diff suppressed because one or more lines are too long
2
os/gres/testdata/testdata.go
vendored
2
os/gres/testdata/testdata.go
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user