完整系统

经过前面几章,文件上传系统已经从一个简单接口演进为完整平台。最终架构可以拆成控制面和数据面:

控制面:鉴权、配额、上传任务、元数据、签名、审核状态、审计日志
数据面:客户端直传、对象存储、分片合并、CDN 分发、异步扫描

控制面由业务服务掌握,因为它需要理解用户、租户、权限和文件状态。数据面交给对象存储、CDN 和异步任务系统承载,因为它们更适合处理大文件、大带宽和耗时任务。

最终链路

一次完整上传可以这样发生:

  1. 客户端申请上传任务,提交文件名、大小、类型和 hash。
  2. 业务服务校验权限、配额和文件策略,创建 upload_task
  3. 服务端返回对象存储分片上传签名。
  4. 客户端直传分片到对象存储。
  5. 客户端提交完成请求,服务端校验分片并触发合并。
  6. 文件状态进入 scanning,异步扫描服务处理安全与内容审核。
  7. 扫描通过后状态变为 available
  8. 用户访问文件时,业务服务校验权限并生成 CDN 签名 URL。
  9. CDN 命中直接返回,未命中则回源对象存储。

这条链路把大流量从业务服务中移走,同时保留了业务侧对权限和状态的控制。

核心表设计

文件系统至少需要三类数据:

数据作用
file_metadata文件归属、大小、类型、状态、对象 key、hash
upload_task / upload_part分片上传任务、分片状态、过期时间
file_audit_log上传、下载、删除、审核、风险处置记录

不要把所有信息塞进一张文件表。上传任务是临时过程,文件元数据是长期事实,审计日志是不可随意修改的追踪记录。

关键决策回顾

  1. 本地存储还是对象存储:早期本地存储快,但对象存储更适合扩容、备份和跨地域访问。
  2. 服务端中转还是客户端直传:中转实现简单,直传能显著降低业务服务带宽压力。
  3. 单次上传还是分片上传:小文件单次上传足够,大文件必须支持分片和断点续传。
  4. 实时扫描还是异步扫描:实时扫描体验更直接,但会拉长上传耗时;异步扫描更适合大文件和复杂审核。
  5. 直接对象存储访问还是 CDN 访问:对象存储适合源站,CDN 适合大规模分发。

系统设计不是选择最复杂的方案,而是在当前规模下选择能解决主要矛盾、又不会堵死后续演进的方案。

上线检查清单

  • 上传失败是否能恢复,未完成分片是否会自动清理?
  • 文件 hash、大小、类型是否在服务端校验?
  • 业务服务是否避免承载大文件下载流量?
  • 私有文件是否只能通过短期签名 URL 访问?
  • CDN 缓存是否有版本化、刷新和回源保护策略?
  • 审核失败或删除后,CDN 缓存是否会被失效?
  • 审计日志是否覆盖上传、下载、删除和风险处置?
  • 对象存储成本、回源率、上传成功率是否有监控和告警?

课程总结

文件上传系统的难点不在“接收一个文件”,而在持续处理增长带来的复杂度:文件越来越大、用户越来越多、访问越来越分散、风险越来越多。一个好的架构应该让传输、存储、处理、分发和治理各自承担合适的职责。

当你下次设计上传功能时,可以先问三个问题:

  • 这个文件系统现在处于哪个阶段?
  • 当前最大的瓶颈是上传成功率、下载延迟、存储成本,还是安全风险?
  • 今天的方案会不会阻碍明天接入分片、对象存储、CDN 和审计?

能回答这些问题,就已经从“写上传接口”进入了“设计文件平台”的视角。