# 压缩包解包Skill 设计 ## 1. Skill 定位 `压缩包解包Skill` 负责压缩包解包,是资料包导入链路中的文件展开能力。它需要支持 `zip`、`rar`、`7z`,并确保解包过程安全、可追踪、可复核。 本 Skill 的输出是“解包后的文件树”,不是文档审核结论。 英文实现标识建议使用 `ArchiveExtractionSkill`,用于 Python 类名和 Tool Registry 注册处理器。 ## 2. 输入 ```python @dataclass class ArchiveExtractionInput: archive_path: Path target_dir: Path source_archive_name: str max_file_count: int = 1000 max_total_size: int | None = None ``` ## 3. 输出 ```python @dataclass class ArchiveExtractionOutput: status: str archive_type: str extracted_files: list[ExtractedFile] skipped_items: list[SkippedArchiveItem] warnings: list[dict] ``` `ExtractedFile` 字段: 1. `absolute_path` 2. `relative_path` 3. `file_size` 4. `source_archive_name` 5. `file_hash` ## 4. 支持格式与技术 | 格式 | 技术 | |---|---| | `zip` | Python 标准库 `zipfile` | | `rar` | 纯 Python rar 解析依赖,优先选择不依赖系统命令的库 | | `7z` | `py7zr` | V1 可以先完成 `zip`,同时保留 `rar`、`7z` 的接口和失败提示。正式验收前需要补齐纯 Python 解包能力。 ## 5. 核心方法 ### 5.1 `run(input) -> ArchiveExtractionOutput` 主入口方法。 处理顺序: 1. 识别压缩包类型。 2. 打开压缩包。 3. 遍历成员文件。 4. 校验成员路径安全性。 5. 校验数量和大小限制。 6. 解包到批次隔离目录。 7. 生成解包结果。 ### 5.2 `detect_archive_type(path) -> str` 根据扩展名和文件头识别压缩包类型。 返回: 1. `zip` 2. `rar` 3. `7z` 4. `unsupported` ### 5.3 `validate_member_path(member_name) -> str` 路径安全校验。 拒绝: 1. 绝对路径。 2. 包含 `..` 的路径。 3. Windows 盘符路径。 4. 空路径。 5. 控制字符。 ### 5.4 `extract_zip(input) -> list[ExtractedFile]` 使用 `zipfile` 解包。 ### 5.5 `extract_rar(input) -> list[ExtractedFile]` 使用纯 Python rar 依赖解包。 如果当前环境依赖未安装,返回 `unsupported_archive`,并提示需要安装对应依赖。 ### 5.6 `extract_7z(input) -> list[ExtractedFile]` 使用 `py7zr` 解包。 ### 5.7 `build_file_hash(path) -> str` 使用 `sha256` 生成文件指纹,用于重复文件识别。 ## 6. 状态设计 | 状态 | 含义 | |---|---| | `extracted` | 解包成功 | | `partial_extracted` | 部分成员解包失败 | | `empty_archive` | 压缩包为空 | | `encrypted_archive` | 加密压缩包 | | `unsupported_archive` | 格式不支持 | | `path_rejected` | 存在危险路径 | | `extract_failed` | 解包失败 | ## 7. 异常处理 1. 加密压缩包:不尝试暴力解析,标记为待人工处理。 2. 路径穿越:拒绝危险成员并记录安全拦截。 3. 超大压缩包:超过配置限制时停止处理。 4. 成员数量过多:停止处理并提示资料包异常。 5. 文件名乱码:保留原始名称,展示层提示人工复核。 ## 8. 测试要点 1. 普通 zip 解包成功。 2. 多层目录相对路径被保留。 3. `../evil.docx` 被拒绝。 4. 空压缩包返回 `empty_archive`。 5. 不支持格式返回 `unsupported_archive`。 6. 解包后文件哈希生成稳定。