2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 07:57:21 +08:00

feat: 重构压缩解压

This commit is contained in:
耗子
2024-10-28 00:10:24 +08:00
parent 0d8a26ccb6
commit 54cc556d17
5 changed files with 100 additions and 431 deletions

93
pkg/io/compress.go Normal file
View File

@@ -0,0 +1,93 @@
package io
import (
"errors"
"os/exec"
"path/filepath"
)
type FormatArchive string
const (
Zip FormatArchive = "zip"
Gz FormatArchive = "gz"
Bz2 FormatArchive = "bz2"
Tar FormatArchive = "tar"
TarGz FormatArchive = "tar.gz"
Xz FormatArchive = "xz"
SevenZip FormatArchive = "7z"
)
// Compress 压缩文件
func Compress(src []string, dst string, format FormatArchive) error {
var cmd *exec.Cmd
switch format {
case Zip:
cmd = exec.Command("zip", append([]string{"-r", "-o", dst}, src...)...)
case Gz:
cmd = exec.Command("tar", append([]string{"-czf", dst}, src...)...)
case Bz2:
cmd = exec.Command("tar", append([]string{"-cjf", dst}, src...)...)
case Tar:
cmd = exec.Command("tar", append([]string{"-cf", dst}, src...)...)
case TarGz:
cmd = exec.Command("tar", append([]string{"-czf", dst}, src...)...)
case Xz:
cmd = exec.Command("tar", append([]string{"-cJf", dst}, src...)...)
case SevenZip:
cmd = exec.Command("7z", append([]string{"a", "-y", dst}, src...)...)
default:
return errors.New("unsupported format")
}
return cmd.Run()
}
// UnCompress 解压文件
func UnCompress(src string, dst string, format FormatArchive) error {
var cmd *exec.Cmd
switch format {
case Zip:
cmd = exec.Command("unzip", "-o", src, "-d", dst)
case Gz:
cmd = exec.Command("tar", "-xzf", src, "-C", dst)
case Bz2:
cmd = exec.Command("tar", "-xjf", src, "-C", dst)
case Tar:
cmd = exec.Command("tar", "-xf", src, "-C", dst)
case TarGz:
cmd = exec.Command("tar", "-xzf", src, "-C", dst)
case Xz:
cmd = exec.Command("tar", "-xJf", src, "-C", dst)
case SevenZip:
cmd = exec.Command("7z", "x", "-y", src, "-o"+dst)
default:
return errors.New("unsupported format")
}
return cmd.Run()
}
// FormatArchiveByPath 根据文件后缀获取压缩格式
func FormatArchiveByPath(path string) (FormatArchive, error) {
switch filepath.Ext(path) {
case ".zip":
return Zip, nil
case ".gz":
return Gz, nil
case ".bz2":
return Bz2, nil
case ".tar":
return Tar, nil
case ".tar.gz":
return TarGz, nil
case ".xz":
return Xz, nil
case ".7z":
return SevenZip, nil
default:
return "", errors.New("unknown format")
}
}

View File

@@ -1,33 +1,9 @@
package io
import (
"archive/zip"
"context"
"errors"
stdio "io"
"os"
"path"
"path/filepath"
"strings"
"github.com/mholt/archiver/v4"
)
type FormatArchive string
const (
Zip FormatArchive = "zip"
Gz FormatArchive = "gz"
Bz2 FormatArchive = "bz2"
Tar FormatArchive = "tar"
TarGz FormatArchive = "tar.gz"
Xz FormatArchive = "xz"
SevenZip FormatArchive = "7z"
)
var (
ErrFormatNotSupport = errors.New("不支持此格式")
ErrNotDirectory = errors.New("目标不是目录")
)
// Write 写入文件
@@ -71,126 +47,6 @@ func FileInfo(path string) (os.FileInfo, error) {
return os.Stat(path)
}
// Compress 压缩文件
func Compress(src []string, dst string, format FormatArchive) error {
// 不支持7z
if format == SevenZip {
return ErrFormatNotSupport
}
arch := getFormat(format)
srcMap := make(map[string]string, len(src))
for _, s := range src {
base := filepath.Base(s)
srcMap[s] = base
}
dir := filepath.Dir(dst)
if !Exists(dir) {
if err := Mkdir(dir, 0755); err != nil {
return err
}
}
files, err := archiver.FilesFromDisk(nil, srcMap)
if err != nil {
return err
}
out, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0755)
if err != nil {
return err
}
defer out.Close()
err = arch.Archive(context.Background(), out, files)
if err != nil {
_ = Remove(dst)
}
return nil
}
// UnCompress 解压文件
func UnCompress(src string, dst string, format FormatArchive) error {
handler := func(ctx context.Context, f archiver.File) error {
info := f.FileInfo
fileName := f.NameInArchive
filePath := filepath.Join(dst, fileName)
if f.FileInfo.IsDir() {
if err := Mkdir(filePath, info.Mode()); err != nil {
return err
}
return nil
}
parentDir := path.Dir(filePath)
if !Exists(parentDir) {
if err := Mkdir(parentDir, info.Mode()); err != nil {
return err
}
}
r, err := f.Open()
if err != nil {
return err
}
w, err := os.OpenFile(filePath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, info.Mode())
if err != nil {
return err
}
defer r.Close()
defer w.Close()
if _, err = stdio.Copy(w, r); err != nil {
return err
}
return nil
}
arch := getFormat(format)
file, err := os.Open(src)
if err != nil {
return err
}
defer file.Close()
if !Exists(dst) {
if err = Mkdir(dst, 0755); err != nil {
return err
}
}
if !IsDir(dst) {
return ErrNotDirectory
}
return arch.Extract(context.Background(), file, nil, handler)
}
// FormatArchiveByPath 根据文件后缀获取压缩格式
func FormatArchiveByPath(path string) (FormatArchive, error) {
switch filepath.Ext(path) {
case ".zip":
return Zip, nil
case ".gz":
return Gz, nil
case ".bz2":
return Bz2, nil
case ".tar":
return Tar, nil
case ".tar.gz":
return TarGz, nil
case ".xz":
return Xz, nil
case ".7z":
return SevenZip, nil
default:
return "", errors.New("unknown format")
}
}
// IsSymlink 判读是否为软链接
func IsSymlink(mode os.FileMode) bool {
return mode&os.ModeSymlink != 0
@@ -215,28 +71,3 @@ func GetSymlink(path string) string {
func TempFile(dir, prefix string) (*os.File, error) {
return os.CreateTemp(dir, prefix)
}
func getFormat(f FormatArchive) archiver.CompressedArchive {
format := archiver.CompressedArchive{}
switch f {
case Tar:
format.Archival = archiver.Tar{}
case TarGz, Gz:
format.Compression = archiver.Gz{}
format.Archival = archiver.Tar{}
case Zip:
format.Archival = archiver.Zip{
Compression: zip.Deflate,
}
case Bz2:
format.Compression = archiver.Bz2{}
format.Archival = archiver.Tar{}
case Xz:
format.Compression = archiver.Xz{}
format.Archival = archiver.Tar{}
case SevenZip:
format.Archival = archiver.SevenZip{}
}
return format
}