From c880caa770abc1721198f95f3ff43986e3c631df Mon Sep 17 00:00:00 2001 From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com> Date: Mon, 16 Oct 2023 03:34:15 -0500 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=83=85=E5=86=B5=E4=B8=8B=20zip=20=E6=96=87=E4=BB=B6=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=E8=A7=A3=E5=8E=8B=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#2565)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs https://github.com/1Panel-dev/1Panel/issues/1245 Refs https://github.com/1Panel-dev/1Panel/issues/263 --- backend/utils/cmd/cmd.go | 14 +++++++-- backend/utils/files/archiver.go | 11 +++++-- backend/utils/files/file_op.go | 54 ++------------------------------- backend/utils/files/tar.go | 12 +++----- backend/utils/files/zip.go | 43 ++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 63 deletions(-) create mode 100644 backend/utils/files/zip.go diff --git a/backend/utils/cmd/cmd.go b/backend/utils/cmd/cmd.go index c7dfa59df..359834dad 100644 --- a/backend/utils/cmd/cmd.go +++ b/backend/utils/cmd/cmd.go @@ -144,9 +144,19 @@ func ExecScript(scriptPath, workDir string) (string, error) { func ExecCmd(cmdStr string) error { cmd := exec.Command("bash", "-c", cmdStr) - err := cmd.Run() + output, err := cmd.CombinedOutput() if err != nil { - return err + return fmt.Errorf("error : %v, output: %s", err, output) + } + return nil +} + +func ExecCmdWithDir(cmdStr, workDir string) error { + cmd := exec.Command("bash", "-c", cmdStr) + cmd.Dir = workDir + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("error : %v, output: %s", err, output) } return nil } diff --git a/backend/utils/files/archiver.go b/backend/utils/files/archiver.go index 57b7e8c83..55df9cafb 100644 --- a/backend/utils/files/archiver.go +++ b/backend/utils/files/archiver.go @@ -7,17 +7,22 @@ import ( ) type ShellArchiver interface { - Compress() error - Extract(dstDir string) error + Extract(filePath, dstDir string) error + Compress(sourcePaths []string, dstFile string) error } -func NewShellArchiver(compressType CompressType) (*TarArchiver, error) { +func NewShellArchiver(compressType CompressType) (ShellArchiver, error) { switch compressType { case Tar: if err := checkCmdAvailability("tar"); err != nil { return nil, err } return NewTarArchiver(compressType), nil + case Zip: + if err := checkCmdAvailability("zip"); err != nil { + return nil, err + } + return NewZipArchiver(), nil default: return nil, buserr.New("unsupported compress type") } diff --git a/backend/utils/files/file_op.go b/backend/utils/files/file_op.go index 2194f1c21..1d78157e3 100644 --- a/backend/utils/files/file_op.go +++ b/backend/utils/files/file_op.go @@ -386,10 +386,7 @@ func (f FileOp) Compress(srcRiles []string, dst string, name string, cType Compr switch cType { case Zip: - if err := ZipFile(files, out); err != nil { - _ = f.DeleteFile(dstFile) - return err - } + return NewZipArchiver().Compress(srcRiles, dstFile) default: err = format.Archive(context.Background(), out, files) if err != nil { @@ -415,13 +412,12 @@ func decodeGBK(input string) (string, error) { func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error { switch cType { - case Tar: + case Tar, Zip: shellArchiver, err := NewShellArchiver(cType) if err != nil { return err } - shellArchiver.FilePath = srcFile - return shellArchiver.Extract(dst) + return shellArchiver.Extract(srcFile, dst) default: format := getFormat(cType) handler := func(ctx context.Context, archFile archiver.File) error { @@ -475,7 +471,6 @@ func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error } return format.Extract(context.Background(), input, nil, handler) } - return nil } func (f FileOp) Backup(srcFile string) (string, error) { @@ -511,46 +506,3 @@ func (f FileOp) CopyAndBackup(src string) (string, error) { } return backupPath, nil } - -func ZipFile(files []archiver.File, dst afero.File) error { - zw := zip.NewWriter(dst) - defer zw.Close() - - for _, file := range files { - hdr, err := zip.FileInfoHeader(file) - if err != nil { - return err - } - hdr.Name = file.NameInArchive - if file.IsDir() { - if !strings.HasSuffix(hdr.Name, "/") { - hdr.Name += "/" - } - hdr.Method = zip.Store - } - w, err := zw.CreateHeader(hdr) - if err != nil { - return err - } - if file.IsDir() { - continue - } - - if file.LinkTarget != "" { - _, err = w.Write([]byte(filepath.ToSlash(file.LinkTarget))) - if err != nil { - return err - } - } else { - fileReader, err := file.Open() - if err != nil { - return err - } - _, err = io.Copy(w, fileReader) - if err != nil { - return err - } - } - } - return nil -} diff --git a/backend/utils/files/tar.go b/backend/utils/files/tar.go index 92bbc5abd..d74c6da2f 100644 --- a/backend/utils/files/tar.go +++ b/backend/utils/files/tar.go @@ -3,28 +3,26 @@ package files import ( "fmt" "github.com/1Panel-dev/1Panel/backend/utils/cmd" - "strings" ) type TarArchiver struct { Cmd string - FilePath string CompressType CompressType } -func NewTarArchiver(compressType CompressType) *TarArchiver { +func NewTarArchiver(compressType CompressType) ShellArchiver { return &TarArchiver{ Cmd: "tar", CompressType: compressType, } } -func (t TarArchiver) Compress(SourcePaths []string) error { - return cmd.ExecCmd(fmt.Sprintf("%s %s %s %s", t.Cmd, t.getOptionStr("compress"), t.FilePath, strings.Join(SourcePaths, " "))) +func (t TarArchiver) Extract(FilePath string, dstDir string) error { + return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), FilePath, dstDir)) } -func (t TarArchiver) Extract(dstDir string) error { - return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), t.FilePath, dstDir)) +func (t TarArchiver) Compress(sourcePaths []string, dstFile string) error { + return nil } func (t TarArchiver) getOptionStr(Option string) string { diff --git a/backend/utils/files/zip.go b/backend/utils/files/zip.go new file mode 100644 index 000000000..984537573 --- /dev/null +++ b/backend/utils/files/zip.go @@ -0,0 +1,43 @@ +package files + +import ( + "fmt" + "github.com/1Panel-dev/1Panel/backend/global" + "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/backend/utils/common" + "path" + "strings" + "time" +) + +type ZipArchiver struct { +} + +func NewZipArchiver() ShellArchiver { + return &ZipArchiver{} +} + +func (z ZipArchiver) Extract(filePath, dstDir string) error { + if err := checkCmdAvailability("unzip"); err != nil { + return err + } + return cmd.ExecCmd(fmt.Sprintf("unzip -qo %s -d %s", filePath, dstDir)) +} + +func (z ZipArchiver) Compress(sourcePaths []string, dstFile string) error { + tmpFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("%s%s.zip", common.RandStr(50), time.Now().Format("20060102150405"))) + op := NewFileOp() + defer func() { + _ = op.DeleteFile(tmpFile) + }() + baseDir := path.Dir(sourcePaths[0]) + relativePaths := make([]string, len(sourcePaths)) + for i, sp := range sourcePaths { + relativePaths[i] = path.Base(sp) + } + cmdStr := fmt.Sprintf("zip -qr %s %s", tmpFile, strings.Join(relativePaths, " ")) + if err := cmd.ExecCmdWithDir(cmdStr, baseDir); err != nil { + return err + } + return op.Rename(tmpFile, dstFile) +}