原创

文件上传系统

paste-image-1784771140199.png

很多 SaaS 产品都会遇到文件上传:头像、图片、PDF、合同、附件、数据表、音频、视频、导入文件。

文件上传看起来只是一个表单功能,但真正上线后会牵扯很多问题:文件大小、格式校验、存储路径、权限控制、安全扫描、上传进度、失败重试、CDN、删除策略和成本。

如果一开始设计太随意,后面文件一多,系统会很难维护。

不要把文件直接存进数据库

新手最容易犯的错误,是把文件内容直接存进数据库。

数据库适合存结构化数据,比如用户、订单、项目、文件记录;不适合存大量二进制文件。文件本身应该放到对象存储里,比如 S3、R2、OSS、COS、GCS 等。

数据库里只保存文件元数据:

file_id
owner_id
bucket
object_key
file_name
mime_type
size
status
created_at

这样数据库负责“文件是谁的、在哪里、是什么状态”,对象存储负责保存真正的文件内容。

上传路径不要直接暴露业务结构

文件在对象存储里的路径要设计清楚。

不要使用用户原始文件名作为唯一路径,也不要把敏感业务信息直接写进路径。原始文件名可能重复,可能包含特殊字符,也可能暴露隐私。

更推荐使用系统生成的 key:

uploads/{user_id}/{file_id}/{safe_file_name}

或者:

uploads/{yyyy}/{mm}/{file_id}

文件展示时可以保留原始文件名,但存储路径应该由系统控制。

推荐使用预签名上传

早期很多人会让文件先上传到自己的业务服务器,再由服务器转存到对象存储。

这种方式简单,但大文件一多,业务服务器会承受大量带宽和内存压力。更好的方式是预签名上传。

流程是:

1. 前端请求后端创建上传凭证
2. 后端校验用户权限和文件信息
3. 后端生成预签名 URL
4. 前端直接上传到对象存储
5. 上传完成后通知后端确认
6. 后端更新文件状态

这样文件数据不需要经过你的业务服务器,系统更稳,也更省资源。

上传前要做基本校验

不要相信前端传来的文件。

上传前后都要做校验:文件大小、扩展名、MIME 类型、业务限制、用户剩余额度、上传次数、文件数量。

前端校验用于减少用户等待,后端校验用于保护系统。对象存储上传策略也可以限制文件大小和类型。

例如:

头像:只允许 jpg/png/webp,最大 5MB
PDF:只允许 application/pdf,最大 20MB
导入表格:只允许 csv/xlsx,最大 10MB
视频:限制格式、大小和时长

校验规则越清楚,后面越少脏数据。

上传完成不等于文件可用

文件上传成功,只代表文件到了存储系统,不代表它已经可以使用。

很多文件还需要后续处理:图片压缩、缩略图生成、病毒扫描、PDF 解析、音视频转码、表格解析、内容安全检测。

因此文件表里应该有状态字段:

pending_upload
uploaded
processing
ready
failed
deleted

用户上传完成后,可以先显示“处理中”,等后台任务处理完再变成可用。

文件权限要单独设计

文件权限不能只靠 URL 隐藏。

如果是私有文件,用户访问时应该先经过你的业务系统校验权限,再生成临时访问 URL,或者通过受控下载接口返回。

常见权限问题包括:

用户 A 访问用户 B 的文件
团队成员访问已删除项目文件
公开分享链接泄露私密文件
离职成员仍能访问旧文件
临时 URL 有效期太长

文件通常包含隐私和业务数据,权限设计要比普通页面更谨慎。

公共文件和私有文件要分开

不是所有文件都需要私有。

比如公开头像、公开封面图、文章配图,可以放在公共 bucket 或走 CDN。合同、发票、导入数据、用户附件、内部文档,应该放在私有 bucket。

公共文件追求访问速度和缓存,私有文件追求权限安全和可审计。

不要把所有文件都混在一个权限模型里。

上传进度和失败重试很重要

文件上传和普通表单不同,用户会等待。

如果上传大文件时没有进度条、没有取消按钮、没有失败提示,用户会不知道系统是否卡住。

至少要提供:

上传进度
上传中状态
失败提示
重新上传
取消上传
大小限制提示
格式限制提示

文件上传体验越清楚,客服问题越少。

删除文件要有策略

用户删除文件时,是否立刻从对象存储删除?

这要看业务。很多系统会先软删除数据库记录,再异步清理对象存储。这样可以避免误删,也能给恢复和审计留空间。

你需要考虑:

用户删除后是否可恢复
文件是否被多个业务对象引用
对象存储是否有生命周期策略
是否需要定期清理孤儿文件
是否需要保留审计记录

文件删除不是简单的 delete,尤其在团队协作和付费业务里。

成本要提前估算

文件系统的成本不只包括存储。

还包括上传流量、下载流量、CDN 流量、图片处理、视频转码、请求次数、备份、跨区域复制。

如果你的产品允许用户上传大文件或视频,成本可能很快上升。早期就要设置大小限制、配额和清理策略。

不要等账单异常后才想起限制上传。

一个文件上传系统结构

可以按下面结构设计:

前端:
选择文件 / 校验 / 进度 / 重试

后端:
权限校验 / 创建文件记录 / 生成预签名 URL / 确认上传

对象存储:
保存原始文件 / 权限控制 / 生命周期

后台任务:
扫描 / 压缩 / 解析 / 转码 / 生成缩略图

数据库:
文件元数据 / 状态 / 所属用户 / 权限 / 业务关联

这比“一个上传接口”更接近真实系统。

写在最后

文件上传系统的关键,不是把文件传上去,而是让文件从上传、存储、处理、访问、删除到审计都有清晰规则。

早期最推荐的结构是:对象存储保存文件,数据库保存元数据,预签名 URL 直接上传,后台任务异步处理,权限访问单独控制。

下一篇,我们继续聊存储选择:图片存储怎么选

正文到此结束
Loading...