OSS Hub:为什么要做一个统一对象存储管理平台
OSS Hub:为什么要做一个统一对象存储管理平台
对象存储很适合放图片、视频、构建产物、配置文件和归档数据,但云厂商控制台通常更偏向基础设施管理,而不是团队日常使用。
当 Bucket 数量逐渐增加,实际遇到的问题往往不再是“能不能上传”,而是:
- 文件分散在不同云厂商和不同 Bucket 中,需要频繁切换控制台。
- 对象只能按 Key 浏览,缺少面向业务的搜索、标签和最近上传记录。
- 团队成员不适合直接持有 AccessKey,也不应该拥有整个云账号的权限。
- 浏览器上传、大文件分片、预览、下载和 CORS 配置需要每个项目重复实现。
- 文件可能被其它程序写入、覆盖或删除,数据库记录和远端对象会逐渐产生偏差。
- 阿里云 OSS 与 S3 兼容服务的 SDK、签名方式和扩展能力并不完全一致。
OSS Hub 就是在这个背景下产生的。它的目标是在对象存储之上增加一层统一的业务管理能力,同时保持文件内容仍然由对象存储承载。
文章结构
这个系列包含四篇文章:
- 本文:项目目的、使用场景、整体架构、核心模块和数据模型。
- 后端篇:认证权限、多云适配、文件浏览、直传、分片上传、标签和数据对账。
- 前端篇:桌面端与移动端、文件工作台、上传队列、预览和实际演示流程。
- 部署篇:初始化、生产构建、SQLite/PostgreSQL、OpenAPI、测试和后续演进。
项目定位
OSS Hub 是一个前后端一体的对象存储资源管理后台。
它不替代对象存储,而是把对象存储原本偏底层的 API 整理成团队可以直接使用的产品能力:
- 在一个界面中管理多套云存储配置。
- 使用统一方式接入阿里云 OSS 和 S3 兼容服务。
- 按目录实时浏览远端对象,并通过数据库索引完成搜索和标签筛选。
- 使用浏览器预签名直传,避免文件内容经过业务服务器。
- 对大文件执行可恢复的分片上传。
- 按云存储划分团队与读写权限。
- 发现对象存储与数据库之间的缺失、变化和未登记对象。
- 提供 Bucket 生命周期、防盗链和 CORS 管理入口。
适合的使用场景包括:
- 企业或小团队内部文件中心。
- 图片、视频、RAW 文件等媒体素材管理。
- 构建产物、安装包、日志和配置文件管理。
- 多云对象存储统一入口。
- 需要定期核对远端对象和业务索引的数据管理系统。
项目目标
这个项目的目标可以分为五层。
第一层:统一入口
用户不需要记住不同云厂商控制台、Region、Bucket 和 Endpoint,只需要登录 OSS Hub,再从顶部选择当前云存储。
文件浏览、搜索、上传、标签和管理页面会自动切换到当前 Bucket。没有访问权限的云存储不会出现在选择器中。

第二层:保护云凭据
AccessKey 只保存在后端,并使用独立配置密钥加密入库。前端不会拿到明文 AK/SK。
上传时,后端根据用户权限、目标路径、文件类型和上传参数生成短期预签名 URL;浏览器只使用这个 URL 把文件直接写入对象存储。
第三层:增加业务索引
对象存储擅长按 Key 读取对象,但不擅长复杂业务查询。OSS Hub 使用数据库维护文件索引,从而支持:
- 按原始文件名、存储文件名和 ObjectKey 搜索。
- 按路径前缀限定范围。
- 按多个标签组合筛选。
- 展示最近上传文件。
- 保存图片元数据、上传人和操作状态。
数据库不是远端对象的替代品,而是一个面向业务查询的索引层。
第四层:建立权限边界
系统把权限分为平台权限和云存储权限:
admin:全局超级权限。oss-hub.admin:OSS Hub 平台管理员。oss-hub.user:允许登录平台。storage.<key>.admin:管理指定云存储。storage.<key>.read:只读访问指定云存储。
这种模型让一个用户可以管理 A Bucket、只读 B Bucket,同时完全看不到 C Bucket。
第五层:处理数据偏差
真实系统中,对象不一定全部由 OSS Hub 创建。CI、脚本、云控制台或其它应用都可能直接操作 Bucket。
因此系统必须同时回答三个问题:
- 远端存在、数据库也存在,内容是否发生变化?
- 数据库存在、远端不存在,是否需要清理索引?
- 远端存在、数据库不存在,是否需要导入登记?
OSS Hub 通过分步扫描、问题记录、重新检查、导入和清理操作完成这个闭环。
整体架构
项目采用 npm workspaces 管理前后端:
oss-hub/├── backend/ # Fastify + TypeScript + Prisma├── frontend/ # Vue 3 + Vite + Pinia├── docs/ # 产品、API、部署和接入文档├── scripts/ # 构建、迁移、OpenAPI 和生产准备脚本├── test/ # 后端、前端与 Playwright 测试└── package.json # workspace 与统一命令运行时由四个部分组成:
这里最重要的设计是:
- 控制请求经过后端。
- 文件内容尽量由浏览器直接传到对象存储。
- 数据库保存管理信息和搜索索引。
- 对象存储仍然是文件内容的最终事实来源。
技术栈
后端主要使用:
- Node.js + TypeScript。
- Fastify 5。
- Prisma 6。
- SQLite,另有 PostgreSQL schema 和迁移脚本。
ali-oss与 AWS SDK v3。jose负责 JWT、JWKS 和本地 token。- Zod 负责输入校验。
archiver负责批量归档下载。exifr负责图片元数据读取。
前端主要使用:
- Vue 3。
- Vite 6。
- Pinia。
- Vue Router。
- Tailwind CSS。
- Axios。
- CodeMirror,用于 JSON 等文本内容的只读展示。
- lucide-vue-next 图标。
核心模块
认证与用户
OSS Hub 支持三种认证模式:
sso:只使用外部 OAuth/OIDC。local:只使用内置用户名和密码。both:同时提供两种登录方式。
外部 token 通过 JWT/JWKS 验证,SSO 用户第一次进入系统时会同步成本地用户记录。内置账号则由后端签发本地 JWT。
云存储配置
每条云存储配置包含:
- 唯一 Key 和显示名称。
- 云服务商类型。
- SDK 协议:阿里云 OSS 或 S3。
- Region、Bucket、Endpoint、公共访问域名。
- 加密后的访问凭据。
- 上传重命名、覆盖策略和命名模板。
- 不登记路径前缀。
云厂商分类用于界面展示,真正决定后端实现的是 SDK 协议。

文件与目录
文件页面按对象 Key 的前缀和分隔符实时浏览 Bucket。目录并不是数据库中的实体,而是对象 Key 形成的逻辑层级。
系统同时显示:
- 已登记文件:远端存在,数据库中也有
FileObject。 - 未登记对象:远端存在,但数据库中还没有索引。
- 逻辑文件夹:由公共前缀产生。
搜索与标签
搜索读取数据库索引,而不是扫描整个 Bucket。标签又分为两类:
- 系统标签:保存在 OSS Hub 数据库中,适合业务分类和组合筛选。
- Object 标签:直接读写对象存储原生标签,适合生命周期、计费或其它云侧规则。
两者用途不同,因此没有被合并成同一套数据。
上传与下载
小文件使用预签名 PUT URL 直传。
超过默认阈值的大文件进入分片上传流程,前端按配置的分片大小切分文件,并行上传多个分片,最后由后端完成合并和登记。
下载使用短期预签名 GET URL。批量下载则由后端读取多个对象并生成压缩流。
管理与对账
云存储管理员可以管理:
- 团队成员与存储级权限。
- 索引同步和差异问题。
- Bucket 生命周期规则。
- Bucket CORS。
- 阿里云 OSS 防盗链。
- Object 标签预设。
- 文件命名规则。
数据模型
数据库模型围绕四组信息展开。
身份与权限
User:SSO 用户或内置用户。Permission:平台权限或云存储权限。UserPermission:用户与权限的多对多关系。
云存储与文件
CloudStorage:Bucket、协议、加密配置和上传策略。FileObject:文件索引、ObjectKey、大小、ETag、状态和上传人。UploadSession:直传或分片上传会话。ImageMetadata、ImageRawPair:图片元数据和图片/RAW 配对信息。
标签
Tag、TagNamespace、FileTag:系统标签体系。ObjectTagPreset:对象存储原生标签的预设模板。
对账与审计
StorageSyncRun:一次分步同步任务。StorageSyncIssue:缺失对象或内容变化问题。AuditLog:记录管理操作和关键文件操作。
为什么同时需要远端浏览和数据库搜索
这是项目中最容易混淆的边界。
如果所有页面都只读数据库:
- 看不到外部程序刚刚写入的对象。
- 数据库记录可能已经失真。
- 用户会误以为数据库就是 Bucket 本身。
如果所有页面都实时扫描对象存储:
- 无法高效做复杂搜索和多标签组合。
- 大 Bucket 的查询成本高、等待时间长。
- 很难保存上传人、业务标签和操作状态。
OSS Hub 的选择是:
- 文件浏览以对象存储实时列表为主。
- 搜索和标签查询以数据库索引为主。
- 对账模块负责发现两者之间的偏差。
项目的取舍
不代理普通文件上传
文件经过后端会增加带宽、内存和磁盘压力,也会让大文件上传更容易受应用服务重启影响。因此普通上传默认使用预签名直传。
不向前端下发永久凭据
浏览器只拿到短期、限定对象 Key 和请求方法的 URL。即使 URL 泄漏,影响范围也远小于 AK/SK 泄漏。
不强行抹平所有云厂商差异
通用能力进入 StorageProvider 接口;阿里云图片处理、防盗链等扩展能力则保留协议能力判断。这样既能复用主链路,也不会制造“所有供应商都支持”的假象。
默认支持单实例,也准备数据库演进路径
SQLite 降低本地部署和个人使用门槛;项目同时维护 PostgreSQL schema、复制、校验、切换和回滚脚本,为更正式的部署预留路径。
演示重点
如果第一次演示 OSS Hub,推荐按下面顺序:
- 登录并切换当前云存储。
- 在文件页面浏览目录、切换列表和图标视图。
- 上传一个小文件和一个大文件,观察两种上传链路。
- 打开图片或文本预览。
- 给文件添加系统标签和 Object 标签。
- 在搜索页按文件名和标签找到文件。
- 在管理页运行索引同步,展示差异问题。
- 切换到移动端,展示操作 Sheet 和移动端预览。
后面的文章会分别展开这些实现。
部分内容可能已过时
OSS Hub 对象存储管理平台
记录 OSS Hub 从项目定位、多云对象存储适配、浏览器直传、索引对账,到 Vue 管理后台、部署和工程化收尾的完整实现。
March7th