基础上传

第一版文件上传系统通常长这样:

浏览器 -> 业务服务 -> 本地磁盘
                 -> 数据库记录

它的优点很明显:实现快、依赖少、调试简单。用户选择文件,服务端接收 multipart 请求,把文件写入指定目录,再保存一条元数据记录:

字段含义
file_id文件唯一标识
owner_id上传者
filename原始文件名
content_type文件类型
size文件大小
storage_path存储路径
status上传、可用、删除等状态

这张表很重要。不要把文件系统只理解成“磁盘上的文件”,业务真正依赖的是文件元数据:谁拥有这个文件、当前是否可访问、是否通过审核、生命周期到什么时候结束。

第一版接口

基础上传至少需要三个接口:

  1. POST /files:上传文件,返回 file_id
  2. GET /files/{file_id}:获取文件元数据或下载地址。
  3. DELETE /files/{file_id}:软删除文件,避免误删后无法恢复。

上传接口要做基础校验:

  • 文件大小不能超过当前业务限制。
  • 文件类型不能只信任扩展名,要结合 Content-Type 和文件头魔数判断。
  • 文件名不能直接用于磁盘路径,避免路径穿越。
  • 写入文件和写入数据库要有补偿机制,避免只有文件没有记录,或只有记录没有文件。

这一版的问题

基础上传能让产品跑起来,但它不是终点。

首先,业务服务器会变成存储服务器。一旦扩容到多台机器,文件可能只存在其中一台,请求打到另一台就找不到。其次,上传和下载都占用业务服务带宽,大文件会拖慢普通 API。再次,单次上传不可恢复,用户网络断开就只能重来。

因此,第一版的设计目标不是“完美”,而是为后续演进留出边界:

  • 文件 ID 与物理路径解耦。
  • 元数据表中保留 status,支持异步处理和审核。
  • 下载不要把本地路径暴露给用户。
  • 上传大小限制要明确,超过限制的文件交给后续分片方案。

完成这些,基础上传就具备了继续演进的空间。