Asset Service
多数后台框架交付的是“上传到本地目录、返回一个 URL”。它在开发环境能跑,进生产就出问题:容器重启或扩容后文件消失、私有文件没有访问校验、URL 长期暴露、每个项目重写一遍 OSS/S3 适配、大文件上传占满应用服务器带宽。
StackRivet 把文件作为一等的 Asset Service:在一处统一管理资产元数据、存储适配、上传下载安全和业务引用。
核心规则:存 assetId,不存 URL
Section titled “核心规则:存 assetId,不存 URL”业务表存 assetId,绝不存裸文件 URL。URL 在需要时通过 Asset API 获取——因此它可以短期有效、经过权限校验、且与你用哪种存储后端无关。
业务行 → assetId → Asset API →(权限校验)→ 短期 signed URL这正是私有文件保持私有、且能在不改业务代码的情况下切换存储后端的关键。
一个存储适配器,三种后端
Section titled “一个存储适配器,三种后端”单一 StorageAdapter 接口覆盖 Local Dev、S3 兼容(如 MinIO、AWS S3)和阿里云 OSS。该适配器:
- 绝不把云厂商 SDK 对象泄露到业务层。
- 把错误转换为统一异常类型。
- 从配置注入 endpoint / bucket / region / 凭据(环境变量,绝不提交进代码仓库)。
- 默认签发短期 signed URL。
从本地存储切到 S3 或 OSS 是改配置(STACKRIVET_STORAGE_TYPE),不是改代码。见配置对象存储指南。
系统生成的 object key
Section titled “系统生成的 object key”存储 object key 由系统生成——用户无法控制,原始文件名只保存在元数据里:
{env}/{tenantId}/{yyyy}/{MM}/{dd}/{assetId}.{extension}# 例如 prod/default/2026/05/27/01JABC.pdf私有文件永不返回永久 URL。
资产走一个小状态机:
stateDiagram-v2 [*] --> pending pending --> active: 上传完成 pending --> deleted: 取消 / 过期 active --> deleted: 软删除 deleted --> [*]
Community 实现 pending、active、deleted。Enterprise 环境可按合规与安全要求扩展生命周期状态。
| 文件 | 路径 |
|---|---|
| 小文件(≤ 8 MB) | 经后端中转,写入存储适配器 |
| 大文件 | 预签名直传——文件直达对象存储,应用服务器不承载完整文件流量 |
| 超大文件 | 分片上传会话(initiate / complete / abort) |
上传响应会返回稳定的 assetId,客户端围绕资产记录重试,不需要保存裸 URL 或云厂商 object key。
私有访问在服务端校验
Section titled “私有访问在服务端校验”私有文件的下载 URL 只有在权限校验之后才签发,经由 AssetAccessPolicy SPI:
public interface AssetAccessPolicy { boolean canRead(CurrentUser user, Asset asset); boolean canDelete(CurrentUser user, Asset asset);}默认上传者可读,系统管理员可读可删,业务模块可注册自己的策略。无权限下载返回 403;未知/超限/禁止类型的上传返回 415 或 413。
Community 包含 Local / S3 兼容 / 阿里云 OSS、私有 signed URL、小文件 + 大文件 + 分片上传、安全校验和业务引用。回收站、CDN 域名、图片缩放/水印、独立资产访问日志属于 Pro;病毒扫描、Object Lock 和 GCS/Azure/COS/OBS属于 Enterprise——见价格页。