fix: 解决解压 .tar 文件失败的问题 (#2562)

This commit is contained in:
zhengkunwang 2023-10-16 02:48:06 -05:00 committed by GitHub
parent 8efe0c8bed
commit 90af56511c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 153 additions and 56 deletions

View file

@ -76,3 +76,14 @@ func WithNameAndErr(Key string, name string, err error) BusinessError {
Err: err,
}
}
func WithName(Key string, name string) BusinessError {
paramMap := map[string]interface{}{}
if name != "" {
paramMap["name"] = name
}
return BusinessError{
Msg: Key,
Map: paramMap,
}
}

View file

@ -89,6 +89,7 @@ var (
ErrFileIsExit = "ErrFileIsExit"
ErrFileUpload = "ErrFileUpload"
ErrFileDownloadDir = "ErrFileDownloadDir"
ErrCmdNotFound = "ErrCmdNotFound"
)
// mysql

View file

@ -62,6 +62,7 @@ ErrLinkPathNotFound: "Target path does not exist!"
ErrFileIsExit: "File already exists!"
ErrFileUpload: "Failed to upload file {{.name}} {{.detail}}"
ErrFileDownloadDir: "Download folder not supported"
ErrCmdNotFound: "{{ .name}} command does not exist, please install this command on the host first"
#website
ErrDomainIsExist: "Domain is already exist"

View file

@ -62,6 +62,7 @@ ErrLinkPathNotFound: "目標路徑不存在!"
ErrFileIsExit: "文件已存在!"
ErrFileUpload: "{{ .name }} 上傳文件失敗 {{ .detail}}"
ErrFileDownloadDir: "不支持下載文件夾"
ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令"
#website
ErrDomainIsExist: "域名已存在"

View file

@ -62,6 +62,7 @@ ErrLinkPathNotFound: "目标路径不存在!"
ErrFileIsExit: "文件已存在!"
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail}}"
ErrFileDownloadDir: "不支持下载文件夹"
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
#website
ErrDomainIsExist: "域名已存在"

View file

@ -0,0 +1,31 @@
package files
import (
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
)
type ShellArchiver interface {
Compress() error
Extract(dstDir string) error
}
func NewShellArchiver(compressType CompressType) (*TarArchiver, error) {
switch compressType {
case Tar:
if err := checkCmdAvailability("tar"); err != nil {
return nil, err
}
return NewTarArchiver(compressType), nil
default:
return nil, buserr.New("unsupported compress type")
}
}
func checkCmdAvailability(cmdStr string) error {
if cmd.Which(cmdStr) {
return nil
}
return buserr.WithName(cmdStr, constant.ErrCmdNotFound)
}

View file

@ -339,19 +339,7 @@ func (f FileOp) GetDirSize(path string) (float64, error) {
return dirSize, nil
}
type CompressType string
const (
Zip CompressType = "zip"
Gz CompressType = "gz"
Bz2 CompressType = "bz2"
Tar CompressType = "tar"
TarGz CompressType = "tar.gz"
Xz CompressType = "xz"
)
func getFormat(cType CompressType) archiver.CompressedArchive {
format := archiver.CompressedArchive{}
switch cType {
case Tar:
@ -426,58 +414,68 @@ func decodeGBK(input string) (string, error) {
}
func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error {
format := getFormat(cType)
handler := func(ctx context.Context, archFile archiver.File) error {
info := archFile.FileInfo
if isIgnoreFile(archFile.Name()) {
return nil
switch cType {
case Tar:
shellArchiver, err := NewShellArchiver(cType)
if err != nil {
return err
}
fileName := archFile.NameInArchive
var err error
if header, ok := archFile.Header.(cZip.FileHeader); ok {
if header.NonUTF8 && header.Flags == 0 {
fileName, err = decodeGBK(fileName)
if err != nil {
return err
shellArchiver.FilePath = srcFile
return shellArchiver.Extract(dst)
default:
format := getFormat(cType)
handler := func(ctx context.Context, archFile archiver.File) error {
info := archFile.FileInfo
if isIgnoreFile(archFile.Name()) {
return nil
}
fileName := archFile.NameInArchive
var err error
if header, ok := archFile.Header.(cZip.FileHeader); ok {
if header.NonUTF8 && header.Flags == 0 {
fileName, err = decodeGBK(fileName)
if err != nil {
return err
}
}
}
}
filePath := filepath.Join(dst, fileName)
if archFile.FileInfo.IsDir() {
if err := f.Fs.MkdirAll(filePath, info.Mode()); err != nil {
filePath := filepath.Join(dst, fileName)
if archFile.FileInfo.IsDir() {
if err := f.Fs.MkdirAll(filePath, info.Mode()); err != nil {
return err
}
return nil
} else {
parentDir := path.Dir(filePath)
if !f.Stat(parentDir) {
if err := f.Fs.MkdirAll(parentDir, info.Mode()); err != nil {
return err
}
}
}
fr, err := archFile.Open()
if err != nil {
return err
}
return nil
} else {
parentDir := path.Dir(filePath)
if !f.Stat(parentDir) {
if err := f.Fs.MkdirAll(parentDir, info.Mode()); err != nil {
return err
}
defer fr.Close()
fw, err := f.Fs.OpenFile(filePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, info.Mode())
if err != nil {
return err
}
defer fw.Close()
if _, err := io.Copy(fw, fr); err != nil {
return err
}
}
fr, err := archFile.Open()
if err != nil {
return err
}
defer fr.Close()
fw, err := f.Fs.OpenFile(filePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, info.Mode())
if err != nil {
return err
}
defer fw.Close()
if _, err := io.Copy(fw, fr); err != nil {
return err
}
return nil
return nil
}
input, err := f.Fs.Open(srcFile)
if err != nil {
return err
}
return format.Extract(context.Background(), input, nil, handler)
}
input, err := f.Fs.Open(srcFile)
if err != nil {
return err
}
return format.Extract(context.Background(), input, nil, handler)
return nil
}
func (f FileOp) Backup(srcFile string) (string, error) {

View file

@ -335,3 +335,14 @@ func min(x, y int) int {
}
return y
}
type CompressType string
const (
Zip CompressType = "zip"
Gz CompressType = "gz"
Bz2 CompressType = "bz2"
Tar CompressType = "tar"
TarGz CompressType = "tar.gz"
Xz CompressType = "xz"
)

View file

@ -0,0 +1,40 @@
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 {
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(dstDir string) error {
return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), t.FilePath, dstDir))
}
func (t TarArchiver) getOptionStr(Option string) string {
switch t.CompressType {
case Tar:
if Option == "compress" {
return "cvf"
} else {
return "xf"
}
}
return ""
}

View file

@ -15,6 +15,7 @@ export const Mimetypes = new Map([
['application/x-gzip-compressed', CompressType.TarGz],
['gzip/document', CompressType.TarGz],
['application/x-xz', CompressType.Xz],
['application/octet-stream', CompressType.Tar],
]);
export const Languages = [

View file

@ -502,6 +502,7 @@ const openCompress = (items: File.File[]) => {
};
const openDeCompress = (item: File.File) => {
console.log(item.mimeType);
if (Mimetypes.get(item.mimeType) == undefined) {
MsgWarning(i18n.global.t('file.canNotDeCompress'));
return;