mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +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
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
@ -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 {
|
||||||
|
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…
x
Reference in New Issue
Block a user