diff --git a/agent/utils/files/archiver.go b/agent/utils/files/archiver.go index 4f90a629f..8e9507956 100644 --- a/agent/utils/files/archiver.go +++ b/agent/utils/files/archiver.go @@ -24,6 +24,16 @@ func NewShellArchiver(compressType CompressType) (ShellArchiver, error) { return nil, err } return NewZipArchiver(), nil + case Rar: + if err := checkCmdAvailability("unrar"); err != nil { + return nil, err + } + return NewRarArchiver(), nil + case X7z: + if err := checkCmdAvailability("7z"); err != nil { + return nil, err + } + return NewX7zArchiver(), nil default: return nil, buserr.New("unsupported compress type") } diff --git a/agent/utils/files/file_op.go b/agent/utils/files/file_op.go index dd96e5534..c02cb746d 100644 --- a/agent/utils/files/file_op.go +++ b/agent/utils/files/file_op.go @@ -638,6 +638,18 @@ func (f FileOp) Compress(srcRiles []string, dst string, name string, cType Compr _ = f.DeleteFile(dstFile) return err } + case Rar: + err = NewRarArchiver().Compress(srcRiles, dstFile, secret) + if err != nil { + _ = f.DeleteFile(dstFile) + return err + } + case X7z: + err = NewX7zArchiver().Compress(srcRiles, dstFile, secret) + if err != nil { + _ = f.DeleteFile(dstFile) + return err + } default: err = format.Archive(context.Background(), out, files) if err != nil { @@ -716,7 +728,7 @@ func (f FileOp) decompressWithSDK(srcFile string, dst string, cType CompressType } func (f FileOp) Decompress(srcFile string, dst string, cType CompressType, secret string) error { - if cType == Tar || cType == Zip || cType == TarGz { + if cType == Tar || cType == Zip || cType == TarGz || cType == Rar || cType == X7z { shellArchiver, err := NewShellArchiver(cType) if !f.Stat(dst) { _ = f.CreateDir(dst, 0755) @@ -725,6 +737,10 @@ func (f FileOp) Decompress(srcFile string, dst string, cType CompressType, secre if err = shellArchiver.Extract(srcFile, dst, secret); err == nil { return nil } + } else { + if cType == Rar || cType == X7z { + return err + } } } return f.decompressWithSDK(srcFile, dst, cType) diff --git a/agent/utils/files/fileinfo.go b/agent/utils/files/fileinfo.go index de1326b16..a234656b8 100644 --- a/agent/utils/files/fileinfo.go +++ b/agent/utils/files/fileinfo.go @@ -465,4 +465,6 @@ const ( Xz CompressType = "xz" SdkZip CompressType = "sdkZip" SdkTarGz CompressType = "sdkTarGz" + Rar CompressType = "rar" + X7z CompressType = "7z" ) diff --git a/agent/utils/files/rar.go b/agent/utils/files/rar.go new file mode 100644 index 000000000..9621e0002 --- /dev/null +++ b/agent/utils/files/rar.go @@ -0,0 +1,57 @@ +package files + +import ( + "fmt" + "path" + "time" + + "github.com/1Panel-dev/1Panel/agent/constant" + "github.com/1Panel-dev/1Panel/agent/global" + "github.com/1Panel-dev/1Panel/agent/utils/cmd" + "github.com/1Panel-dev/1Panel/agent/utils/common" +) + +type RarArchiver struct { +} + +func NewRarArchiver() ShellArchiver { + return &RarArchiver{} +} + +func (z RarArchiver) Extract(filePath, dstDir string, _ string) error { + if err := checkCmdAvailability("unrar"); err != nil { + return err + } + return cmd.RunDefaultBashCf("unrar x -y -o+ %q %q", filePath, dstDir) +} + +func (z RarArchiver) Compress(sourcePaths []string, dstFile string, _ string) (err error) { + if err = checkCmdAvailability("rar"); err != nil { + return err + } + tmpFile := path.Join(global.Dir.TmpDir, fmt.Sprintf("%s%s.rar", common.RandStr(50), time.Now().Format(constant.DateTimeSlimLayout))) + op := NewFileOp() + defer func() { + _ = op.DeleteFile(tmpFile) + if err != nil { + _ = op.DeleteFile(dstFile) + } + }() + + baseDir := path.Dir(sourcePaths[0]) + relativePaths := make([]string, len(sourcePaths)) + for i, sp := range sourcePaths { + relativePaths[i] = path.Base(sp) + } + + cmdArgs := append([]string{"a", "-r", tmpFile}, relativePaths...) + cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(baseDir)) + if err = cmdMgr.Run("rar", cmdArgs...); err != nil { + return err + } + + if err = op.Mv(tmpFile, dstFile); err != nil { + return err + } + return nil +} diff --git a/agent/utils/files/x7z.go b/agent/utils/files/x7z.go new file mode 100644 index 000000000..8f29e112a --- /dev/null +++ b/agent/utils/files/x7z.go @@ -0,0 +1,57 @@ +package files + +import ( + "fmt" + "path" + "time" + + "github.com/1Panel-dev/1Panel/agent/constant" + "github.com/1Panel-dev/1Panel/agent/global" + "github.com/1Panel-dev/1Panel/agent/utils/cmd" + "github.com/1Panel-dev/1Panel/agent/utils/common" +) + +type X7zArchiver struct { +} + +func NewX7zArchiver() ShellArchiver { + return &X7zArchiver{} +} + +func (z X7zArchiver) Extract(filePath, dstDir string, _ string) error { + if err := checkCmdAvailability("7z"); err != nil { + return err + } + return cmd.RunDefaultBashCf("7z x -y -o%q %q", dstDir, filePath) +} + +func (z X7zArchiver) Compress(sourcePaths []string, dstFile string, _ string) (err error) { + if err = checkCmdAvailability("7z"); err != nil { + return err + } + tmpFile := path.Join(global.Dir.TmpDir, fmt.Sprintf("%s%s.7z", common.RandStr(50), time.Now().Format(constant.DateTimeSlimLayout))) + op := NewFileOp() + defer func() { + _ = op.DeleteFile(tmpFile) + if err != nil { + _ = op.DeleteFile(dstFile) + } + }() + + baseDir := path.Dir(sourcePaths[0]) + relativePaths := make([]string, len(sourcePaths)) + for i, sp := range sourcePaths { + relativePaths[i] = path.Base(sp) + } + + cmdArgs := append([]string{"a", "-r", tmpFile}, relativePaths...) + cmdMgr := cmd.NewCommandMgr(cmd.WithWorkDir(baseDir)) + if err = cmdMgr.Run("7z", cmdArgs...); err != nil { + return err + } + + if err = op.Mv(tmpFile, dstFile); err != nil { + return err + } + return nil +} diff --git a/frontend/src/enums/files.ts b/frontend/src/enums/files.ts index a2cb0ef28..14b24dd05 100644 --- a/frontend/src/enums/files.ts +++ b/frontend/src/enums/files.ts @@ -5,6 +5,8 @@ export enum CompressType { Tar = 'tar', TarGz = 'tar.gz', Xz = 'xz', + Rar = 'rar', + '7z' = '7z', } export enum CompressExtension { @@ -14,4 +16,18 @@ export enum CompressExtension { tar = '.tar', 'tar.gz' = '.tar.gz', xz = '.tar.xz', + rar = '.rar', + '7z' = '.7z', } + +export const MimetypeByExtensionObject: Record = { + '.zip': 'application/zip', + '.tar': 'application/x-tar', + '.tar.bz2': 'application/x-bzip2', + '.bz2': 'application/x-bzip2', + '.tar.gz': 'application/gzip', + '.gz': 'application/gzip', + '.xz': 'application/x-xz', + '.rar': 'application/x-rar-compressed', + '.7z': 'application/x-7z-compressed', +}; diff --git a/frontend/src/global/mimetype.ts b/frontend/src/global/mimetype.ts index 87ee4edab..fb5f7ee4f 100644 --- a/frontend/src/global/mimetype.ts +++ b/frontend/src/global/mimetype.ts @@ -16,6 +16,9 @@ export const Mimetypes = new Map([ ['gzip/document', CompressType.TarGz], ['application/x-xz', CompressType.Xz], ['application/octet-stream', CompressType.Tar], + ['application/x-rar-compressed', CompressType.Rar], + ['application/vnd.rar', CompressType.Rar], + ['application/x-7z-compressed', CompressType['7z']], ]); export const Languages = [ diff --git a/frontend/src/views/host/file-management/index.vue b/frontend/src/views/host/file-management/index.vue index fc384f859..55efbc3c5 100644 --- a/frontend/src/views/host/file-management/index.vue +++ b/frontend/src/views/host/file-management/index.vue @@ -546,6 +546,7 @@ import VscodeOpenDialog from '@/components/vscode-open/index.vue'; import { debounce } from 'lodash-es'; import TerminalDialog from './terminal/index.vue'; import { Dashboard } from '@/api/interface/dashboard'; +import { CompressExtension, MimetypeByExtensionObject } from '@/enums/files'; const globalStore = GlobalStore(); @@ -962,10 +963,15 @@ const openDeCompress = (item: File.File) => { return; } + if (CompressExtension[Mimetypes.get(item.mimeType)] != item.extension) { + fileDeCompress.mimeType = MimetypeByExtensionObject[item.extension]; + } else { + fileDeCompress.mimeType = item.mimeType; + } + fileDeCompress.name = item.name; fileDeCompress.path = item.path; fileDeCompress.dst = req.path; - fileDeCompress.mimeType = item.mimeType; deCompressRef.value.acceptParams(fileDeCompress); };