feat: Support compress 7z and rar format files (#8776)

This commit is contained in:
2025-05-21 22:25:40 +08:00 committed by GitHub
parent 80475bd8db
commit eac4e15ef5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 169 additions and 2 deletions

View file

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

View file

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

View file

@ -465,4 +465,6 @@ const (
Xz CompressType = "xz"
SdkZip CompressType = "sdkZip"
SdkTarGz CompressType = "sdkTarGz"
Rar CompressType = "rar"
X7z CompressType = "7z"
)

57
agent/utils/files/rar.go Normal file
View file

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

57
agent/utils/files/x7z.go Normal file
View file

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

View file

@ -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<string, string> = {
'.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',
};

View file

@ -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 = [

View file

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