> 新工程迁移说明（2026-10-01）：本文记录旧版设计或旧工程历史状态。当前实现以 `ZipHarbor/ZipHarbor.xcodeproj` 为准，参见 [迁移映射](05-新工程迁移与功能映射.md)、[新架构](06-新工程技术架构.md) 和 [最终验收报告](07-新工程最终验收报告.md)。

# 压缩解压缩 iOS App 技术方案文档

**文档版本**：v1.0  
**目标**：在一个完整版本中交付稳定、可维护、隐私优先的压缩解压缩工具。  
**推荐技术栈**：Swift、SwiftUI、必要位置使用 UIKit、Swift Concurrency、Document Picker 和 File Provider。建议最低支持 iOS/iPadOS 17，以覆盖所需的 SwiftUI 导航、照片选择、Shortcuts 和多窗口能力，并降低系统兼容分支数量。

## 1. 技术目标与约束

### 技术目标

- 支持本地文件、iCloud Drive 和第三方 File Provider。
- 支持大文件和大目录的流式处理。
- 压缩和解压任务可观察、可取消、可恢复。
- 不把文件内容、密码、文件名和路径上传到服务器。
- 对异常压缩包安全失败，不让 App 崩溃或越权写入。
- iPhone、iPad、深色模式、VoiceOver、键盘和拖拽统一支持。

### 关键约束

- iOS 沙盒不能直接访问任意路径，外部文件必须经安全作用域 URL 或系统文件选择器授权。
- iOS 后台执行时间有限，长任务必须支持检查点和恢复，不能依赖应用长期驻留后台。
- 解压第三方格式需要评估库的许可证、RAR/7z 商用分发限制和 App Store 合规性。
- 云端文件可能是占位文件，读取前需要等待 File Provider 下载完成。
- 压缩包解析属于不可信输入，必须隔离解析、校验路径并限制资源使用。

## 2. 总体架构

采用分层架构，UI、任务编排、文件系统和压缩引擎相互隔离：

- **SwiftUI / UIKit**：界面和系统交互。
- **Presentation Layer**：ViewModel、导航、权限、任务展示。
- **Application Layer**：导入、归档、解压、任务、预览和分享用例。
- **Domain Layer**：归档条目、任务、解压计划、冲突策略等业务模型。
- **Infrastructure Layer**：文件访问、File Provider、归档引擎、预览、持久化、Keychain 和日志。

推荐模块：

- AppShell
- ArchiveUI
- FileBrowser
- TaskCenter
- ArchiveApplication
- ArchiveDomain
- ArchiveEngine
- FileAccess
- Preview
- Persistence
- Security
- ShareIntegration

### 2.1 模块职责

**AppShell**

- App 生命周期、场景和窗口管理。
- iPhone Tab、iPad Split View、深色模式和语言环境。
- 启动时恢复未完成任务。

**ArchiveUI / FileBrowser**

- 文件列表、归档目录、搜索、排序、多选。
- 只通过 ViewModel 访问用例，不直接调用压缩库。

**ArchiveApplication**

提供用户用例：

- ImportArchiveUseCase
- InspectArchiveUseCase
- ExtractArchiveUseCase
- CreateArchiveUseCase
- PreviewEntryUseCase
- MoveCopyDeleteUseCase
- ShareOutputUseCase
- RetryJobUseCase

每个用例负责参数校验、权限生命周期、任务创建和结果映射，不负责具体压缩算法。

**ArchiveDomain**

定义与具体库无关的模型和规则。例如：

- ArchiveDescriptor：归档标识、来源、格式、压缩大小、展开大小、条目数、加密信息。
- ArchiveEntry：相对路径、类型、压缩大小、展开大小、修改时间、加密状态。
- ExtractionPlan：来源、所选条目、目标位置、目录结构策略和冲突策略。
- CreateArchiveRequest：来源条目、输出格式、压缩级别、加密选项和目标位置。
- ArchiveJob：任务类型、状态、进度、检查点、结果和错误。

### 2.2 归档引擎适配层

通过 ArchiveEngine 协议隔离第三方库。协议负责检查归档、异步列出条目、解压、创建和校验。每种库通过 Adapter 实现统一接口。

ZIP 可优先评估 AppleArchive、ZIPFoundation 或 minizip；TAR/GZIP/BZ2 可评估 libarchive；7z 和 RAR 需额外审核组件许可证与商用分发约束。

UI 和业务用例不依赖具体引擎实现。替换或升级库时，归档目录模型和任务界面保持稳定。

### 2.3 FileAccess

统一处理：

- UIDocumentPickerViewController / SwiftUI 文件导入导出。
- 安全作用域 URL 的 start/stop access 生命周期。
- 文件协调和 NSFileCoordinator。
- File Provider 占位文件下载。
- 临时目录、磁盘空间和文件属性。
- 重名、移动、复制、删除和回收站。

所有 File URL 进入领域层前转换为 FileReference，避免把失效的裸路径传到任务中。

### 2.4 Persistence

建议使用 SQLite 或 Core Data 保存：

- 最近文件索引。
- 任务及任务检查点。
- 用户设置和冲突策略。
- 收藏和本地标签。
- 常用压缩/解压方案（格式、级别、目标位置、冲突策略；不包含密码）。
- 回收站索引。

不保存压缩包密码明文、文件内容或完整文件名和路径的分析副本。

密码如用户明确启用“保存密码”，使用 Keychain，并按源文件安全标识加密关联。

## 3. 任务执行设计

### 3.1 状态机

状态依次为：

创建 → 排队 → 获取输入 → 检查归档 → 准备处理 → 处理中 → 校验 → 完成/部分完成/失败/取消。

需要密码时进入等待密码状态；暂停后可恢复到处理中。任务状态必须持久化。App 被系统杀死后，根据检查点恢复或安全标记为“需要重试”。

### 3.2 并发策略

- 默认单任务执行，避免同时读写大量文件导致内存、磁盘和电量压力。
- 多任务队列可以排队，用户手动启用时最多并发两个轻量任务。
- 预览和目录读取采用异步流，不阻塞压缩任务。
- UI 通过 AsyncSequence 接收条目和进度更新。

### 3.3 进度计算

同时维护已处理字节/总字节、已完成条目/总条目、当前速度和滑动平均速度、预计剩余时间。

未知展开大小时显示已处理条目和字节，不伪造百分比。压缩包索引无法提供可靠大小时，使用“正在处理”而不是跳动的错误进度。

### 3.4 取消和恢复

- 每个任务拥有 CancellationHandler。
- 安全检查点位于条目边界和输出文件 flush 后。
- 取消时清理未完成的临时文件。
- 已完成文件写入原子临时文件后再移动到目标位置。
- 恢复时校验已完成文件大小和校验和，避免重复或损坏。

### 3.5 后台执行

- 用户启动的压缩任务使用 beginBackgroundTask 为正在执行的短时任务争取收尾时间，并在系统到期回调中及时保存检查点。
- 不依赖 BGProcessingTaskRequest 保证继续用户当前任务；该 API 只用于系统允许时执行后台维护、索引或恢复检查。
- 后台执行不保证立即获得时间，UI 必须允许任务稍后恢复，并准确显示上次保存的任务状态。
- 不在后台上传文件，不依赖自建服务器。

## 4. 文件和归档安全

### 4.1 路径安全

解压前对每个条目进行：

1. Unicode 规范化。
2. 分隔符和点路径清理。
3. 生成目标 URL 后验证其标准化路径仍位于目标目录内。
4. 拒绝绝对路径、路径穿越、危险符号链接和设备文件。
5. 对过长文件名和非法字符采用明确的安全重命名，并记录结果。

路径验证必须使用标准化后的文件 URL 及文件系统组件比较，不能只用字符串前缀判断（例如 /safe 和 /safe-evil 的前缀关系）。

### 4.2 解压炸弹和资源限制

设置可配置的安全阈值：

- 最大条目数。
- 最大目录深度。
- 最大单文件展开大小。
- 最大总展开大小。
- 压缩比异常阈值。

超过限制时先提示用户；只有用户明确确认且磁盘空间足够才继续。对可疑归档采取保守默认值，避免因极高压缩比占满设备。

### 4.3 密码和加密

- 密码仅存在于内存中的短生命周期对象。
- 不进入日志、崩溃报告、通知、URL 或分析事件。
- 密码输入页面支持显示/隐藏和 Keychain 读取。
- AES-256 创建和解压需要使用经过审核的实现。
- 错误密码与损坏归档要尽量区分，避免让用户重复尝试无关操作。

### 4.4 不可信解析

- 压缩库运行在独立模块，解析失败通过领域错误类型返回。
- 对异常输入执行 fuzz 测试。
- 统一捕获底层库错误，不把 C/C++ 异常直接传播到 UI。
- 任何库升级都重新执行格式兼容和安全回归测试。

## 5. iOS 系统集成

### 5.1 Files 和 Document Picker

- 使用 UIDocumentPickerViewController 选择输入和目标位置。
- 使用 UTType 声明支持的压缩文件类型和导出类型。
- 使用安全作用域书签记录用户明确授权过的位置。
- 导出时使用系统保存面板，而不是默认复制到 App 私有目录。

### 5.2 分享面板

实现 Share Extension 或标准 UIActivityViewController 集成：

- 接收压缩文件直接打开归档详情。
- 接收多个普通文件进入创建压缩包流程。
- 分享压缩包和解压结果到其他 App。
- 不在 Extension 中执行长时间压缩，必要时交给主 App 任务队列。

### 5.3 照片选择

- 使用 PHPickerViewController 或 PhotosPicker。
- 默认只获取用户选择的照片和视频，不请求完整照片库权限。
- 保留原始文件名、扩展名和必要元数据。
- 读取失败的资源在结果页单独列出，不阻塞其他照片。

### 5.4 iPad

- 使用 NavigationSplitView 或 UIKit 多栏导航。
- 支持多窗口、拖放、键盘快捷键、指针和横屏。
- 预览与归档目录并排展示，任务中心使用侧栏或浮层。

### 5.5 App Intents 和 Shortcuts

- 提供打开压缩包、创建 ZIP、查看进行中任务等意图。
- 通过系统文件选择输入，遵守用户授予的文件访问范围。
- Shortcut 不绕过密码输入、冲突确认和安全阈值等必要交互。
- 批处理可以返回任务标识和完成状态；需要用户决策时将控制权交回 App。

## 6. 预览系统

预览层独立于压缩引擎：

1. 引擎以流或临时文件提供条目内容。
2. Preview Provider 根据 UTType 选择 Quick Look、系统 PDF、图片或媒体播放器。
3. 大文件优先流式预览，不默认复制完整文件。
4. 无法预览时提供“导出到其他 App”，不显示空白页。

支持图片、PDF、TXT、RTF、Office 常见格式以及常见音视频的只读预览。预览失败不应影响条目导出。

## 7. 错误模型

定义稳定的领域错误，不直接把底层错误字符串展示给用户：

- unsupportedFormat
- invalidArchive
- incorrectPassword
- missingVolume
- insufficientStorage(required, available)
- unsafePath
- fileProviderUnavailable
- permissionDenied
- cancelled
- partialFailure

每个错误映射到用户能理解的标题、原因说明、一个首选下一步动作，以及可选的技术详情（仅用于用户主动反馈和调试）。

## 8. 性能方案

- 使用分块流式读写，默认块大小通过基准测试确定。
- 目录读取采用增量流和虚拟化列表。
- 输出先写入临时文件，完成后原子移动。
- 对照片和视频不做重复内存拷贝。
- 大文件计算校验和时使用后台任务和进度上报。
- 在任务启动前检查磁盘空间，处理云端下载空间和输出空间的双重需求。
- 使用 Instruments 检查内存峰值、文件句柄、I/O 等待、CPU 和电量。

建议基准场景：

| 场景 | 目标 |
|---|---|
| 100 MB ZIP 目录展示 | 5 秒内显示首屏条目 |
| 1 GB ZIP 解压 | 内存不随总文件大小线性增长 |
| 10,000 条目目录 | 列表滚动无明显卡顿 |
| 100 张照片压缩 | UI 可操作，任务可取消 |
| 云端占位文件 | 下载、解压、输出状态清晰 |

## 9. 测试方案

### 9.1 单元测试

- 格式识别和扩展名不一致。
- 相对路径规范化。
- 冲突策略。
- 空间估算和进度计算。
- 任务状态机和恢复检查点。
- 错误映射和本地化文案键。

### 9.2 集成测试

- Files 导入、导出和安全作用域生命周期。
- 分享面板接收单个和多个文件。
- iCloud 和第三方 File Provider。
- 照片选择器和大批量资源。
- Face ID、通知、深色模式、动态字体。

### 9.3 归档兼容测试

建立固定 fixture 集合：

- ZIP Store、Deflate、Zip64、传统密码、AES。
- RAR 常见版本和密码包。
- 7z 常见压缩算法和密码包。
- TAR/GZIP/BZ2/TGZ/ZIPX。
- 多卷、嵌套目录、Unicode 文件名、emoji、长路径。
- 损坏中央目录、截断文件、错误扩展名和恶意路径。

每个 fixture 验证目录、文件大小、校验和、权限、错误类型和 UI 结果。

### 9.4 安全测试

- Zip Slip 和绝对路径写入。
- 解压炸弹和资源耗尽。
- 符号链接、硬链接和特殊文件。
- 密码出现在日志、崩溃报告、通知或分析中的扫描。
- 第三方库 fuzz 测试。
- 沙盒越权和安全作用域泄漏。

### 9.5 UI 自动化和可用性测试

验证分享面板到解压完成、多选照片到 ZIP 完成、密码错误、重名、空间不足、网络断开、取消和恢复等完整流程，并覆盖 iPhone 小屏、iPad 横屏、深色模式、Dynamic Type 和 VoiceOver。

首次使用测试目标：用户在 60 秒内完成打开 ZIP 并保存文件。

## 10. 隐私、日志和可观测性

### 隐私原则

- 不上传文件内容、文件名、路径、密码和云盘列表。
- 统计只记录匿名任务类型、格式、耗时区间、成功/失败类别和 App 版本。
- 用户可以关闭分析和通知。
- App Store 隐私标签与实际代码保持一致。

### 日志原则

- 默认只记录错误类型、库错误码、任务 ID 和版本信息。
- 文件名、路径、密码使用脱敏占位符或完全省略。
- 用户主动反馈时，提供可选诊断包，不自动上传文件。
- 生产日志分级，避免大量目录条目污染控制台。

## 11. 依赖、许可证和发布

在引入压缩库前完成：

1. 对 ZIP、RAR、7z、TAR/GZIP 的覆盖率评估。
2. 商用分发和 App Store 的许可证审核。
3. 静态链接、动态链接和第三方声明页面确认。
4. 库升级策略和安全通告订阅。
5. 二进制大小、启动时间和隐私清单审核。

发布前检查：

- 所有支持格式 fixture 通过。
- 无已知路径穿越和资源耗尽问题。
- 崩溃、内存、文件句柄和电量基准通过。
- Files、分享、照片、通知和 Face ID 权限文案通过。
- App Store 隐私标签、支持 URL、隐私政策和许可证页完整。
- 免费基础流程没有广告或强制订阅阻断。

## 12. 推荐目录结构

ZipApp/
- App/
- Features/
  - Files/
  - ArchiveDetail/
  - CreateArchive/
  - TaskCenter/
  - Settings/
- Domain/
  - Models/
  - Errors/
  - Policies/
- Application/
  - UseCases/
  - TaskCoordinator/
- Infrastructure/
  - ArchiveEngine/
  - FileAccess/
  - Persistence/
  - Preview/
  - Security/
- ShareExtension/
- Resources/
  - Localizations/
  - Fixtures/
- Tests/
  - UnitTests/
  - IntegrationTests/
  - ArchiveFixtureTests/
  - SecurityTests/
  - UITests/

## 13. 最终技术决策

1. 产品采用本地优先架构，不建设文件上传后端。
2. 所有压缩库通过 ArchiveEngine 适配层接入，避免 UI 和第三方库耦合。
3. 所有任务使用持久化状态机、流式 I/O 和原子输出。
4. 所有外部文件通过 Files、Share、Photos 系统入口获得，不扫描用户整个设备。
5. 先保证 ZIP、RAR、7z 的稳定性，再扩展更多格式；不为了格式数量牺牲安全和可靠性。
6. 通过功能边界控制复杂度，OCR、PDF 编辑、视频转换、浏览器和自建云盘不进入产品。

## 14. 本次实现对齐说明

当前工程位于 `app/`，产品名称为 ZipHarbor，最低支持 iOS 17，使用 SwiftUI、SwiftData 和 `libarchive.xcframework`。

已实现的主链路（运行验证状态见验收报告）：

- Files / 分享面板导入归档到本地库，支持最近列表、收藏、搜索和中英文资源。
- ZIP、7z、RAR、TAR、GZIP、BZIP2 的归档读取；RAR 仅读取，检测到加密 RAR 时给出明确边界提示。
- ZIP AES-256 创建、密码读取和错误密码重试；7z 创建保持为普通归档，7z 密码创建在当前 libarchive XCFramework 中不可用，页面会明确引导使用 ZIP AES。
- 选择性解压、保留目录、重名策略、原子临时文件输出、路径穿越阻断。
- ZIP `.zip.001` 卷组导入与重组；创建端可按 64/128/256/512 MB 生成 ZIP 切片并分享卷组。
- SwiftData 任务历史、进度更新、错误状态、Face ID/设备密码应用锁和深色外观。

有意保持边界的能力：RAR/7z 归档创建以 libarchive 支持为准；不把密码写入历史；暂停/系统杀死后的检查点恢复、通知、快捷指令、回收站和完整的文件管理器仍需要单独补齐，不能从当前版本的界面开关推断为已交付。

### 14.1 验证记录（2026-09-30）

模拟器 `ZipHarborTests` 7/7、`ZipHarborUITests` 1/1 已通过；`simctl` 安装并启动应用成功，截图保存在 `docs/iphone14-home-final.png`。测试期间出现过 iOS 26.5 Accessibility 运行时警告，但最终 UI 流程完成。

实体 iPhone 14（UDID `IPHONE14_UDID`）已完成安装、启动和 `ZipHarborTests` 7/7 真机验证，截图保存在 `docs/iphone14-real-home-final.png`。真机 UI runner 在开启自动化模式时超时，报 `Timed out while enabling automation mode`，需要稳定的设备自动化环境后补跑 UI 页面断言。
