1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 16:29:17 +08:00

fix: 解决部分情况下 zip 文件压缩解压失败的问题 (#2565)

Refs https://github.com/1Panel-dev/1Panel/issues/1245
Refs https://github.com/1Panel-dev/1Panel/issues/263
This commit is contained in:
zhengkunwang 2023-10-16 03:34:15 -05:00 committed by GitHub
parent 90af56511c
commit c880caa770
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 63 deletions

View File

@ -144,9 +144,19 @@ func ExecScript(scriptPath, workDir string) (string, error) {
func ExecCmd(cmdStr string) error { func ExecCmd(cmdStr string) error {
cmd := exec.Command("bash", "-c", cmdStr) cmd := exec.Command("bash", "-c", cmdStr)
err := cmd.Run() output, err := cmd.CombinedOutput()
if err != nil { 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 return nil
} }

View File

@ -7,17 +7,22 @@ import (
) )
type ShellArchiver interface { type ShellArchiver interface {
Compress() error Extract(filePath, dstDir string) error
Extract(dstDir string) error Compress(sourcePaths []string, dstFile string) error
} }
func NewShellArchiver(compressType CompressType) (*TarArchiver, error) { func NewShellArchiver(compressType CompressType) (ShellArchiver, error) {
switch compressType { switch compressType {
case Tar: case Tar:
if err := checkCmdAvailability("tar"); err != nil { if err := checkCmdAvailability("tar"); err != nil {
return nil, err return nil, err
} }
return NewTarArchiver(compressType), nil return NewTarArchiver(compressType), nil
case Zip:
if err := checkCmdAvailability("zip"); err != nil {
return nil, err
}
return NewZipArchiver(), nil
default: default:
return nil, buserr.New("unsupported compress type") return nil, buserr.New("unsupported compress type")
} }

View File

@ -386,10 +386,7 @@ func (f FileOp) Compress(srcRiles []string, dst string, name string, cType Compr
switch cType { switch cType {
case Zip: case Zip:
if err := ZipFile(files, out); err != nil { return NewZipArchiver().Compress(srcRiles, dstFile)
_ = f.DeleteFile(dstFile)
return err
}
default: default:
err = format.Archive(context.Background(), out, files) err = format.Archive(context.Background(), out, files)
if err != nil { if err != nil {
@ -415,13 +412,12 @@ func decodeGBK(input string) (string, error) {
func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error { func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error {
switch cType { switch cType {
case Tar: case Tar, Zip:
shellArchiver, err := NewShellArchiver(cType) shellArchiver, err := NewShellArchiver(cType)
if err != nil { if err != nil {
return err return err
} }
shellArchiver.FilePath = srcFile return shellArchiver.Extract(srcFile, dst)
return shellArchiver.Extract(dst)
default: default:
format := getFormat(cType) format := getFormat(cType)
handler := func(ctx context.Context, archFile archiver.File) error { 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 format.Extract(context.Background(), input, nil, handler)
} }
return nil
} }
func (f FileOp) Backup(srcFile string) (string, error) { func (f FileOp) Backup(srcFile string) (string, error) {
@ -511,46 +506,3 @@ func (f FileOp) CopyAndBackup(src string) (string, error) {
} }
return backupPath, nil 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
}

View File

@ -3,28 +3,26 @@ package files
import ( import (
"fmt" "fmt"
"github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/cmd"
"strings"
) )
type TarArchiver struct { type TarArchiver struct {
Cmd string Cmd string
FilePath string
CompressType CompressType CompressType CompressType
} }
func NewTarArchiver(compressType CompressType) *TarArchiver { func NewTarArchiver(compressType CompressType) ShellArchiver {
return &TarArchiver{ return &TarArchiver{
Cmd: "tar", Cmd: "tar",
CompressType: compressType, CompressType: compressType,
} }
} }
func (t TarArchiver) Compress(SourcePaths []string) error { func (t TarArchiver) Extract(FilePath string, dstDir string) error {
return cmd.ExecCmd(fmt.Sprintf("%s %s %s %s", t.Cmd, t.getOptionStr("compress"), t.FilePath, strings.Join(SourcePaths, " "))) return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), FilePath, dstDir))
} }
func (t TarArchiver) Extract(dstDir string) error { func (t TarArchiver) Compress(sourcePaths []string, dstFile string) error {
return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), t.FilePath, dstDir)) return nil
} }
func (t TarArchiver) getOptionStr(Option string) string { func (t TarArchiver) getOptionStr(Option string) string {

View File

@ -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)
}