7.3 KiB
7.3 KiB
上传模块架构改造
本模块已从 NestJS 架构成功改造为 Hono + Bun 架构,并支持多种存储后端的无感切换。
文件结构
src/upload/
├── tus.ts # TUS 协议服务核心实现
├── upload.index.ts # 资源管理相关函数
├── upload.rest.ts # Hono REST API 路由
├── storage.adapter.ts # 存储适配器系统 🆕
├── storage.utils.ts # 存储工具类 🆕
├── scheduler.ts # 定时清理任务
├── utils.ts # 工具函数
├── types.ts # 类型定义
└── README.md # 本文档
存储适配器系统
支持的存储类型
- 本地存储 (Local) - 文件存储在本地文件系统
- S3 存储 (S3) - 文件存储在 AWS S3 或兼容的对象存储服务
环境变量配置
本地存储配置
STORAGE_TYPE=local
UPLOAD_DIR=./uploads
UPLOAD_EXPIRATION_MS=0 # 0 表示不自动过期(推荐设置)
S3 存储配置
STORAGE_TYPE=s3
S3_BUCKET=your-bucket-name
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
S3_ENDPOINT=https://s3.amazonaws.com # 可选,支持其他 S3 兼容服务
S3_FORCE_PATH_STYLE=false # 可选,路径风格
S3_PART_SIZE=8388608 # 可选,分片大小 (8MB)
S3_MAX_CONCURRENT_UPLOADS=60 # 可选,最大并发上传数
UPLOAD_EXPIRATION_MS=0 # 0 表示不自动过期(推荐设置)
存储类型记录
- 数据库支持: 每个资源记录都包含
storageType
字段,标识文件使用的存储后端 - 自动记录: 上传时自动记录当前的存储类型
- 迁移支持: 支持批量更新现有资源的存储类型标记
不过期设置
- 默认行为: 过期时间默认设为 0,表示文件不会自动过期
- 手动清理: 提供多种手动清理选项
- 灵活控制: 可根据需要设置过期时间,或完全禁用自动清理
无感切换机制
- 单例模式管理:
StorageManager
使用单例模式确保全局一致性 - 自动配置检测: 启动时根据环境变量自动选择存储类型
- 统一接口: 所有存储类型都实现相同的 TUS
DataStore
接口 - 运行时切换: 支持运行时切换存储配置(需要重启生效)
API 端点
资源管理
GET /api/upload/resource/:fileId
- 获取文件资源信息GET /api/upload/resources
- 获取所有资源GET /api/upload/resources/storage/:storageType
- 🆕 根据存储类型获取资源GET /api/upload/resources/status/:status
- 🆕 根据状态获取资源GET /api/upload/resources/uploading
- 🆕 获取正在上传的资源GET /api/upload/stats
- 🆕 获取资源统计信息DELETE /api/upload/resource/:id
- 删除资源PATCH /api/upload/resource/:id
- 更新资源POST /api/upload/cleanup
- 手动触发清理POST /api/upload/cleanup/by-status
- 🆕 根据状态清理资源POST /api/upload/migrate-storage
- 🆕 迁移资源存储类型标记
存储管理
GET /api/upload/storage/info
- 获取当前存储配置信息POST /api/upload/storage/switch
- 切换存储类型POST /api/upload/storage/validate
- 验证存储配置
TUS 协议
OPTIONS /api/upload/*
- TUS 协议选项请求HEAD /api/upload/*
- TUS 协议头部请求POST /api/upload/*
- TUS 协议创建上传PATCH /api/upload/*
- TUS 协议上传数据GET /api/upload/*
- TUS 协议获取状态
新增 API 使用示例
获取存储类型统计
const response = await fetch('/api/upload/stats');
const stats = await response.json();
// {
// total: 150,
// byStatus: { "UPLOADED": 120, "UPLOADING": 5, "PROCESSED": 25 },
// byStorageType: { "local": 80, "s3": 70 }
// }
查询特定存储类型的资源
const response = await fetch('/api/upload/resources/storage/s3');
const s3Resources = await response.json();
迁移存储类型标记
const response = await fetch('/api/upload/migrate-storage', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ from: 'local', to: 's3' }),
});
// { success: true, message: "Migrated 50 resources from local to s3", count: 50 }
手动清理特定状态的资源
const response = await fetch('/api/upload/cleanup/by-status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
status: 'UPLOADING',
olderThanDays: 7,
}),
});
🆕 存储管理示例
获取存储信息
const response = await fetch('/api/upload/storage/info');
const storageInfo = await response.json();
// { type: 'local', config: { directory: './uploads' } }
切换到 S3 存储
const newConfig = {
type: 's3',
s3: {
bucket: 'my-bucket',
region: 'us-west-2',
accessKeyId: 'YOUR_ACCESS_KEY',
secretAccessKey: 'YOUR_SECRET_KEY',
},
};
const response = await fetch('/api/upload/storage/switch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newConfig),
});
验证存储配置
const response = await fetch('/api/upload/storage/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newConfig),
});
const validation = await response.json();
// { valid: true, message: 'Storage configuration is valid' }
特性保留
- TUS 协议支持 - 完全保留原有的断点续传功能
- 文件命名 - 保留安全的文件命名策略
- 资源状态管理 - 保留完整的上传状态跟踪
- 自动清理 - 保留过期文件清理功能(默认禁用)
- 数据库集成 - 保留 Prisma ORM 数据库操作
🆕 新增特性
- 多存储后端支持 - 支持本地存储和 S3 存储
- 无感切换 - 运行时可切换存储类型
- 配置验证 - 提供存储配置验证功能
- 存储信息查询 - 可查询当前存储配置
- 统一日志 - 存储操作统一日志记录
- 🆕 存储类型记录 - 数据库记录每个资源的存储类型
- 🆕 灵活清理 - 支持按状态、时间等条件清理
- 🆕 统计分析 - 提供详细的资源统计信息
- 🆕 不过期设置 - 默认不自动过期,避免意外删除
运行
服务启动时会自动:
- 根据环境变量初始化存储适配器
- 初始化 TUS 服务器
- 注册 REST API 路由
- 启动定时清理任务(如果启用)
支持的存储切换场景:
- 开发环境使用本地存储
- 生产环境使用 S3 存储
- 混合云部署灵活切换
- 存储迁移时批量更新资源标记
💡 最佳实践
- 过期设置: 推荐设置
UPLOAD_EXPIRATION_MS=0
避免文件意外过期 - 存储记录: 利用数据库中的
storageType
字段追踪文件位置 - 定期清理: 使用手动清理 API 定期清理不需要的资源
- 监控统计: 使用统计 API 监控存储使用情况
- 迁移策略: 在存储迁移时先更新环境变量,再使用迁移 API 更新数据库标记
无需代码修改,仅通过环境变量即可实现存储后端的无感切换。