这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
完整系统
经过前面几章,文件上传系统已经从一个简单接口演进为完整平台。最终架构可以拆成控制面和数据面:
控制面:鉴权、配额、上传任务、元数据、签名、审核状态、审计日志
数据面:客户端直传、对象存储、分片合并、CDN 分发、异步扫描
控制面由业务服务掌握,因为它需要理解用户、租户、权限和文件状态。数据面交给对象存储、CDN 和异步任务系统承载,因为它们更适合处理大文件、大带宽和耗时任务。
最终链路
一次完整上传可以这样发生:
- 客户端申请上传任务,提交文件名、大小、类型和 hash。
- 业务服务校验权限、配额和文件策略,创建
upload_task。 - 服务端返回对象存储分片上传签名。
- 客户端直传分片到对象存储。
- 客户端提交完成请求,服务端校验分片并触发合并。
- 文件状态进入
scanning,异步扫描服务处理安全与内容审核。 - 扫描通过后状态变为
available。 - 用户访问文件时,业务服务校验权限并生成 CDN 签名 URL。
- CDN 命中直接返回,未命中则回源对象存储。
这条链路把大流量从业务服务中移走,同时保留了业务侧对权限和状态的控制。
核心表设计
文件系统至少需要三类数据:
| 数据 | 作用 |
|---|---|
| file_metadata | 文件归属、大小、类型、状态、对象 key、hash |
| upload_task / upload_part | 分片上传任务、分片状态、过期时间 |
| file_audit_log | 上传、下载、删除、审核、风险处置记录 |
不要把所有信息塞进一张文件表。上传任务是临时过程,文件元数据是长期事实,审计日志是不可随意修改的追踪记录。
关键决策回顾
- 本地存储还是对象存储:早期本地存储快,但对象存储更适合扩容、备份和跨地域访问。
- 服务端中转还是客户端直传:中转实现简单,直传能显著降低业务服务带宽压力。
- 单次上传还是分片上传:小文件单次上传足够,大文件必须支持分片和断点续传。
- 实时扫描还是异步扫描:实时扫描体验更直接,但会拉长上传耗时;异步扫描更适合大文件和复杂审核。
- 直接对象存储访问还是 CDN 访问:对象存储适合源站,CDN 适合大规模分发。
系统设计不是选择最复杂的方案,而是在当前规模下选择能解决主要矛盾、又不会堵死后续演进的方案。
上线检查清单
- 上传失败是否能恢复,未完成分片是否会自动清理?
- 文件 hash、大小、类型是否在服务端校验?
- 业务服务是否避免承载大文件下载流量?
- 私有文件是否只能通过短期签名 URL 访问?
- CDN 缓存是否有版本化、刷新和回源保护策略?
- 审核失败或删除后,CDN 缓存是否会被失效?
- 审计日志是否覆盖上传、下载、删除和风险处置?
- 对象存储成本、回源率、上传成功率是否有监控和告警?
课程总结
文件上传系统的难点不在“接收一个文件”,而在持续处理增长带来的复杂度:文件越来越大、用户越来越多、访问越来越分散、风险越来越多。一个好的架构应该让传输、存储、处理、分发和治理各自承担合适的职责。
当你下次设计上传功能时,可以先问三个问题:
- 这个文件系统现在处于哪个阶段?
- 当前最大的瓶颈是上传成功率、下载延迟、存储成本,还是安全风险?
- 今天的方案会不会阻碍明天接入分片、对象存储、CDN 和审计?
能回答这些问题,就已经从“写上传接口”进入了“设计文件平台”的视角。
