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, // zip 中的路径(已使用 /) "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 }