datai/datai-scenes/datai-scene-salesforce/docs/decisions/adr/0016-file-storage-and-extract.md
Kris 2e6f087732 docs: 完成REQ-010-17和REQ-010-2的文档创建
- 完成REQ-010-17(性能优化和限流处理)的所有6个阶段
  - 创建ADR文档:0026-performance-optimization.md
  - 创建Prompt文档:027-performance-optimization.md
  - 创建会话记录:20260119-performance-optimization.md
  - 创建变更记录:20260119-performance-optimization.md
  - 创建复盘报告:20260119-performance-optimization-retro.md
  - 更新index.md和CHANGELOG.md

- 完成REQ-010-2(基础实体类和Mapper创建)的前3个阶段
  - 更新ADR文档:0011-entity-mapper-create.md
  - 创建Prompt文档:002-entity-mapper-create.md
  - 更新index.md

所有文档均按照SSOT方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录和闭环复盘。
2026-01-19 10:06:09 +08:00

13 KiB
Raw Blame History

架构决策记录 - 文件存储和解压处理

背景

在 REQ-010-6元数据拉取核心功能我们已经实现了从 Salesforce Metadata API 拉取元数据的功能。拉取的元数据以 Zip 文件形式返回,需要对这些 Zip 文件进行存储和解压处理。

本需求面临的主要问题包括:

  1. Zip 文件存储需要支持本地文件系统和 OSS 存储两种方式
  2. 需要处理大文件(可能达到数百 MB避免内存溢出
  3. 文件路径管理需要防止路径遍历攻击
  4. 存储空间需要监控和告警机制
  5. 需要自动清理过期文件以释放存储空间

相关约束条件:

  • 必须基于现有的 Spring Boot 3 + Vue 3 技术栈
  • 必须在 datai-salesforce-metadata 模块下实现
  • 必须支持大文件处理,内存使用合理
  • 必须验证路径安全性,防止路径遍历攻击

决策

1. 文件存储方案

决策: 使用策略模式实现本地文件系统和 OSS 存储的统一接口,通过配置文件动态切换存储方式。

理由:

  • 策略模式符合开闭原则,易于扩展新的存储方式
  • 统一接口简化了业务代码,降低耦合度
  • 配置文件动态切换支持不同环境的灵活部署
  • 本地文件系统适合开发环境OSS 适合生产环境

实现方案:

  • 定义 IFileStorageService 接口,包含存储、读取、删除等方法
  • 实现 LocalStorageServiceOssStorageService 两个策略类
  • 使用 Spring 的 @ConditionalOnProperty 注解根据配置自动选择实现类
  • 配置项:file.storage.typelocal/oss

2. 文件解压方案

决策: 使用 ZipInputStream 实现流式解压,避免一次性加载整个 Zip 文件到内存。

理由:

  • ZipInputStream 支持流式处理,内存占用可控
  • 可以边读取边解压,适合处理大文件
  • Java 标准库,无需额外依赖
  • 性能稳定,经过充分验证

实现方案:

  • 使用 ZipInputStream 逐条读取 ZipEntry
  • 使用 BufferedOutputStream 写入解压后的文件
  • 支持进度回调,实时报告解压进度
  • 支持取消操作,通过标志位中断解压过程

3. 文件路径管理方案

决策: 使用 Java NIO 的 Path API 处理路径,配合正则表达式验证路径安全性。

理由:

  • Path API 提供了跨平台的路径处理能力
  • normalize() 方法可以规范化路径,消除 ...
  • startsWith() 方法可以验证路径是否在允许的目录下
  • 正则表达式可以进一步限制文件名和路径格式

实现方案:

  • 定义 PathValidator 工具类,提供路径验证方法
  • 使用 path.normalize().startsWith(basePath) 验证路径
  • 使用正则表达式限制文件名(不允许包含特殊字符)
  • 拒绝包含 .. 的路径,防止路径遍历攻击

4. 存储空间管理方案

决策: 使用定时任务定期检查存储空间,当空间不足时发送告警通知。

理由:

  • 定时任务实现简单,无需额外依赖
  • 可以灵活配置检查频率和告警阈值
  • 告警通知可以集成现有的通知机制
  • 支持多种告警方式(邮件、短信、钉钉等)

实现方案:

  • 使用 Spring 的 @Scheduled 注解实现定时任务
  • 使用 FileStore.getUsableSpace() 获取可用空间
  • 配置项:file.storage.warning-threshold(告警阈值,如 80%
  • 告警通知使用现有的 INotificationService 接口

5. 文件清理方案

决策: 使用定时任务定期清理过期文件,支持配置清理策略。

理由:

  • 定时任务实现简单,易于维护
  • 可以灵活配置清理策略(保留天数、文件大小等)
  • 清理日志记录完整,便于审计
  • 支持手动清理和自动清理两种方式

实现方案:

  • 使用 Spring 的 @Scheduled 注解实现定时任务
  • 配置项:file.cleanup.retention-days(保留天数)
  • 清理策略:根据文件最后修改时间判断是否过期
  • 清理前记录日志,清理后更新统计信息
  • 提供 RESTful API 接口支持手动清理

备选方案

1. 文件存储方案备选

备选方案 A: 使用 Spring 的 Resource 抽象,通过 ResourceLoader 动态加载不同的存储实现。

优点:

  • Spring 原生支持,无需额外代码
  • 支持多种资源类型classpath、file、http、ftp 等)

缺点:

  • 不支持 OSS 存储
  • 接口不够灵活,难以扩展
  • 不符合本项目需求

备选方案 B: 使用 Apache Commons VFS 实现虚拟文件系统。

优点:

  • 支持多种文件系统local、ftp、sftp、s3 等)
  • 统一的接口,易于使用

缺点:

  • 引入额外依赖,增加项目复杂度
  • 性能不如直接实现
  • 过于重量级,不符合本项目需求

2. 文件解压方案备选

备选方案 A: 使用 Apache Commons Compress 库。

优点:

  • 支持多种压缩格式zip、tar、gzip 等)
  • 功能丰富API 友好

缺点:

  • 引入额外依赖
  • 对于简单的 Zip 解压Java 标准库已经足够
  • 增加项目复杂度

备选方案 B: 先将 Zip 文件完整加载到内存,再解压。

优点:

  • 实现简单

缺点:

  • 内存占用高,不适合大文件
  • 可能导致内存溢出
  • 不符合性能要求

3. 文件路径管理方案备选

备选方案 A: 使用字符串操作处理路径。

优点:

  • 实现简单

缺点:

  • 容易出错,跨平台兼容性差
  • 需要手动处理路径分隔符
  • 安全性难以保证

备选方案 B: 使用第三方路径验证库。

优点:

  • 功能丰富,安全性高

缺点:

  • 引入额外依赖
  • 增加项目复杂度
  • Java NIO 的 Path API 已经足够

4. 存储空间管理方案备选

备选方案 A: 使用第三方监控工具(如 Prometheus + Grafana

优点:

  • 功能强大,可视化效果好
  • 支持多种告警方式

缺点:

  • 引入额外依赖,增加运维复杂度
  • 部署成本高
  • 对于简单的存储空间监控,过于重量级

备选方案 B: 使用操作系统级别的监控(如 cron + shell 脚本)。

优点:

  • 不依赖应用层

缺点:

  • 与应用解耦,难以集成
  • 维护成本高
  • 不符合项目架构

5. 文件清理方案备选

备选方案 A: 使用操作系统的定时任务(如 cron

优点:

  • 不依赖应用层

缺点:

  • 与应用解耦,难以集成
  • 维护成本高
  • 不符合项目架构

备选方案 B: 使用文件系统的自动清理机制(如 tmpwatch

优点:

  • 系统级支持,性能好

缺点:

  • 与应用解耦,难以集成
  • 配置不够灵活
  • 不符合项目架构

影响

系统架构影响

  1. 新增模块: 在 datai-salesforce-metadata 模块下新增 file 包,包含文件存储、解压、路径管理等功能
  2. 接口定义: 定义 IFileStorageService 接口,提供统一的文件存储抽象
  3. 策略模式: 使用策略模式实现不同的存储策略,提高系统扩展性
  4. 定时任务: 新增两个定时任务(存储空间监控、文件清理),需要配置定时任务执行器

开发流程影响

  1. 开发工作量: 需要开发 5 个主要功能模块,预计工作量 3-5 人天
  2. 测试工作量: 需要进行单元测试、集成测试和性能测试,预计工作量 2-3 人天
  3. 代码规范: 需要遵循项目现有的代码规范和设计模式
  4. 文档维护: 需要更新接口文档和 API 文档

运维管理影响

  1. 配置管理: 需要新增配置项(存储类型、告警阈值、保留天数等)
  2. 监控告警: 需要配置存储空间监控和告警通知
  3. 日志管理: 需要记录文件操作日志和清理日志
  4. 存储管理: 需要定期检查存储空间使用情况

风险

技术风险

  1. 大文件处理风险: 大文件处理不当可能导致内存溢出

    • 缓解措施: 使用流式处理,限制内存占用
    • 监控指标: 监控 JVM 内存使用情况
  2. 路径安全风险: 路径验证不完善可能导致路径遍历攻击

    • 缓解措施: 使用 Path API 和正则表达式双重验证
    • 监控指标: 记录所有文件操作日志
  3. OSS 存储风险: OSS 存储不稳定可能导致文件存储失败

    • 缓解措施: 实现重试机制和降级策略
    • 监控指标: 监控 OSS 存储成功率和响应时间

业务风险

  1. 存储空间风险: 存储空间不足可能导致文件存储失败

    • 缓解措施: 实现存储空间监控和告警机制
    • 监控指标: 监控存储空间使用率
  2. 文件清理风险: 文件清理策略不当可能导致重要文件被删除

    • 缓解措施: 清理前记录日志,支持文件恢复
    • 监控指标: 记录清理操作日志

实施风险

  1. 性能风险: 文件解压和清理可能影响系统性能

    • 缓解措施: 使用异步处理,限制并发数
    • 监控指标: 监控系统 CPU 和内存使用情况
  2. 兼容性风险: 不同操作系统的路径处理可能存在兼容性问题

    • 缓解措施: 使用 Java NIO 的 Path API保证跨平台兼容性
    • 监控指标: 在不同操作系统上进行测试

回滚策略

1. 文件存储回滚策略

如果 OSS 存储出现问题,可以立即切换回本地文件系统:

  1. 修改配置文件 file.storage.type=local
  2. 重启应用
  3. 将已存储到 OSS 的文件复制到本地文件系统

2. 文件解压回滚策略

如果流式解压出现问题,可以临时使用完整加载方式:

  1. 修改代码,使用 ZipFile 替代 ZipInputStream
  2. 限制文件大小,避免内存溢出
  3. 优化后重新切换回流式解压

3. 文件清理回滚策略

如果文件清理出现问题,可以立即停止清理任务:

  1. 修改配置文件,禁用定时任务
  2. 恢复被误删的文件(如果有备份)
  3. 修复清理策略后重新启用

4. 整体回滚策略

如果整个功能出现问题,可以回滚到 REQ-010-6 的状态:

  1. 停止使用文件存储和解压功能
  2. 将 Zip 文件临时存储在内存中
  3. 修复问题后重新启用

验收标准

功能验收标准

  1. Zip 文件存储

    • 本地文件系统存储成功
    • OSS 存储成功
    • 存储路径正确
    • 文件完整性验证通过
    • 支持配置动态切换
  2. 文件解压

    • 文件解压成功
    • 支持大文件处理(> 100MB
    • 支持流式解压
    • 内存使用合理(< 512MB
    • 解压文件结构正确
    • 支持进度回调
    • 支持取消操作
  3. 文件路径管理

    • 文件路径管理正常工作
    • 支持路径规范化
    • 支持路径验证
    • 路径格式正确
    • 路径安全性验证通过
    • 防止路径遍历攻击
  4. 存储空间管理

    • 存储空间管理正常工作
    • 支持存储空间监控
    • 支持存储空间告警
    • 存储空间信息准确
    • 告警通知及时
  5. 文件清理

    • 文件清理功能正常工作
    • 支持过期文件自动清理
    • 支持手动清理
    • 清理策略可配置
    • 清理日志记录完整

性能验收标准

  1. 文件存储性能

    • 本地文件系统存储速度 > 50MB/s
    • OSS 存储速度 > 20MB/s
    • 并发存储 10 个文件无性能下降
  2. 文件解压性能

    • 解压速度 > 30MB/s
    • 内存使用 < 512MB
    • 并发解压 5 个文件无性能下降
  3. 存储空间监控性能

    • 监控任务执行时间 < 1s
    • 不影响系统正常运行
  4. 文件清理性能

    • 清理任务执行时间 < 5s
    • 不影响系统正常运行

安全性验收标准

  1. 路径安全

    • 防止路径遍历攻击
    • 防止文件名注入攻击
    • 防止符号链接攻击
  2. 存储安全

    • 文件存储权限正确
    • OSS 存储访问权限正确
    • 文件完整性验证通过

代码质量验收标准

  1. 代码规范

    • 代码符合项目编码规范
    • 有清晰的注释
    • 通过代码审查
  2. 测试覆盖

    • 单元测试覆盖率 > 80%
    • 集成测试覆盖主要场景
    • 性能测试通过
  3. 文档完整

    • 接口文档完整
    • API 文档完整
    • 使用文档完整

视觉锚点

Visual Reference

引用 Canvas 的具体节点或快照:

Status

  • Draft
  • Accepted
  • Superceded

参考资料

列出与该决策相关的参考资料,包括文档、文章或其他资源:

  1. REQ-010-7.md - 文件存储和解压处理需求文档
  2. REQ-010-6.md - 元数据拉取核心功能需求文档
  3. file/index.md - 文件模块 API 文档索引
  4. Java NIO Path API 文档: https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html
  5. Spring Boot 文件上传文档: https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.servlet.spring-multipart
  6. Apache Commons Compress 文档: https://commons.apache.org/proper/commons-compress/