重构:文件系统模块化架构,优化应用启动流程
This commit is contained in:
121
internal/filesystem/zip_helper.go
Normal file
121
internal/filesystem/zip_helper.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// ZipOperation ZIP操作回调函数类型
|
||||
// 用于 withZipReader 通用包装器
|
||||
type ZipOperation func(*zip.ReadCloser) (interface{}, error)
|
||||
|
||||
// withZipReader 通用的ZIP文件操作包装器
|
||||
// 消除重复的打开/关闭逻辑,统一错误处理
|
||||
// 参数:
|
||||
// - zipPath: ZIP文件路径
|
||||
// - operation: 操作回调函数,接收 *zip.ReadCloser,返回任意结果
|
||||
//
|
||||
// 返回:
|
||||
// - interface{}: 操作结果
|
||||
// - error: 错误信息
|
||||
func withZipReader(zipPath string, operation ZipOperation) (interface{}, error) {
|
||||
// 1. 统一验证路径
|
||||
if err := validateZipPath(zipPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 2. 打开 ZIP 文件
|
||||
reader, err := zip.OpenReader(zipPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("打开 zip 文件失败: %v", err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
// 3. 执行操作
|
||||
result, err := operation(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// withZipFile 在ZIP文件中查找特定文件并执行操作
|
||||
// 进一步封装,用于处理单个文件的操作
|
||||
type ZipFileOperation func(*zip.File) (interface{}, error)
|
||||
|
||||
// withZipFile 在ZIP中查找文件并执行操作
|
||||
func withZipFile(zipPath, filePath string, operation ZipFileOperation) (interface{}, error) {
|
||||
return withZipReader(zipPath, func(reader *zip.ReadCloser) (interface{}, error) {
|
||||
// 查找目标文件
|
||||
for _, file := range reader.File {
|
||||
if isMatchFile(file, filePath) {
|
||||
return operation(file)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("文件在 zip 中不存在: %s", filePath)
|
||||
})
|
||||
}
|
||||
|
||||
// isMatchFile 检查文件是否匹配目标路径
|
||||
func isMatchFile(file *zip.File, targetPath string) bool {
|
||||
return file.Name == targetPath ||
|
||||
filepath.Clean(file.Name) == filepath.Clean(targetPath)
|
||||
}
|
||||
|
||||
// openZipFileInReader 在ZIP reader中打开指定文件
|
||||
// 用于读取文件内容的辅助函数
|
||||
func openZipFileInReader(reader *zip.ReadCloser, filePath string) (io.ReadCloser, *zip.File, error) {
|
||||
for _, file := range reader.File {
|
||||
if isMatchFile(file, filePath) {
|
||||
if file.Mode().IsDir() {
|
||||
return nil, nil, fmt.Errorf("不能读取目录")
|
||||
}
|
||||
|
||||
rc, err := file.Open()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("打开 zip 中的文件失败: %v", err)
|
||||
}
|
||||
return rc, file, nil
|
||||
}
|
||||
}
|
||||
return nil, nil, fmt.Errorf("文件在 zip 中不存在: %s", filePath)
|
||||
}
|
||||
|
||||
// readAllFromFile 从文件读取所有内容
|
||||
// 辅助函数,避免重复的 io.ReadAll 调用
|
||||
func readAllFromFile(rc io.ReadCloser) ([]byte, error) {
|
||||
defer rc.Close()
|
||||
return io.ReadAll(rc)
|
||||
}
|
||||
|
||||
// getCompressionMethodString 获取压缩方法字符串描述
|
||||
func getCompressionMethodString(method uint16) string {
|
||||
if method == 8 {
|
||||
return "Deflate"
|
||||
}
|
||||
return "Store"
|
||||
}
|
||||
|
||||
// createFileInfoMap 创建文件信息map(通用格式)
|
||||
func createFileInfoMap(file *zip.File, includeExtra ...bool) map[string]interface{} {
|
||||
info := map[string]interface{}{
|
||||
"name": filepath.Base(file.Name),
|
||||
"path": file.Name,
|
||||
"is_dir": file.Mode().IsDir(),
|
||||
"size": file.UncompressedSize64,
|
||||
"compressed": file.CompressedSize64,
|
||||
"mod_time": file.Modified.Format("2006-01-02 15:04:05"),
|
||||
"method": getCompressionMethodString(file.Method),
|
||||
}
|
||||
|
||||
// 可选:额外信息
|
||||
if len(includeExtra) > 0 && includeExtra[0] {
|
||||
info["mode"] = file.Mode().String()
|
||||
info["comment"] = file.Comment
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
Reference in New Issue
Block a user