You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

235 lines
5.0 KiB

/*
* GodoOS - A lightweight cloud desktop
* Copyright (C) 2024 https://godoos.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package files
import (
"archive/tar"
"archive/zip"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// 压缩文件到指定的目录
func zipCompress(folderPath, zipFilePath string) error {
zipFile, err := os.Create(zipFilePath)
if err != nil {
return err
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
info, err := os.Stat(folderPath)
if err != nil {
return err
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Base(folderPath)
}
filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
relPath, err := filepath.Rel(folderPath, path)
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(baseDir, relPath)
} else {
header.Name = relPath
}
if info.IsDir() {
header.Name += "/"
} else {
header.Method = zip.Deflate
}
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return nil
}
// IsSupportedCompressionFormat 判断文件后缀是否为支持的压缩格式
func IsSupportedFormat(filename string) bool {
supportedFormats := map[string]bool{
".zip": true,
".tar": true,
".gz": true,
}
for format := range supportedFormats {
if strings.HasSuffix(strings.ToLower(filename), format) {
return true
}
}
return false
}
// CompressFileOrFolder 压缩文件或文件夹到指定的压缩文件
func CompressFileOrFolder(sourcePath, compressedFilePath string) error {
if IsSupportedFormat(compressedFilePath) {
return Encompress(sourcePath, compressedFilePath)
}
// 如果压缩文件格式不受支持,则返回错误或采取其他措施
return fmt.Errorf("unsupported compression format for file: %s", compressedFilePath)
}
// Encompress 压缩文件或文件夹到指定的压缩格式
func Encompress(sourcePath, compressedFilePath string) error {
switch filepath.Ext(compressedFilePath) {
case ".zip":
return zipCompress(sourcePath, compressedFilePath)
case ".tar":
return tarCompress(sourcePath, compressedFilePath)
case ".gz":
return tarGzCompress(sourcePath, compressedFilePath)
default:
return fmt.Errorf("unsupported compression format: %s", filepath.Ext(compressedFilePath))
}
}
// tarCompress 使用 tar 格式压缩文件或文件夹
func tarCompress(folderPath, tarFilePath string) error {
// 打开目标文件
tarFile, err := os.Create(tarFilePath)
if err != nil {
return err
}
defer tarFile.Close()
// 创建 tar.Writer
tarWriter := tar.NewWriter(tarFile)
defer tarWriter.Close()
// 遍历文件夹并添加到 tar 文件
err = filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
if err := tarWriter.WriteHeader(header); err != nil {
return err
}
if !info.IsDir() {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(tarWriter, file)
if err != nil {
return err
}
}
return nil
})
return err
}
// tarGzCompress 使用 tar.gz 格式压缩文件或文件夹
func tarGzCompress(folderPath, tarGzFilePath string) error {
// 打开目标文件
gzFile, err := os.Create(tarGzFilePath)
if err != nil {
return err
}
defer gzFile.Close()
// 创建 gzip.Writer
gzWriter := gzip.NewWriter(gzFile)
defer gzWriter.Close()
// 创建 tar.Writer
tarWriter := tar.NewWriter(gzWriter)
defer tarWriter.Close()
// 遍历文件夹并添加到 tar 文件
err = filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
if err := tarWriter.WriteHeader(header); err != nil {
return err
}
if !info.IsDir() {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(tarWriter, file)
if err != nil {
return err
}
}
return nil
})
return err
}