mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-10 17:13:30 +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:
parent
90af56511c
commit
c880caa770
5 changed files with 71 additions and 63 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
43
backend/utils/files/zip.go
Normal file
43
backend/utils/files/zip.go
Normal 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)
|
||||
}
|
Loading…
Reference in a new issue