fenghuo/apps/backend/src/upload/README.md

233 lines
7.3 KiB
Markdown
Raw Normal View History

2025-05-28 08:23:15 +08:00
# 上传模块架构改造
本模块已从 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 # 本文档
```
## 存储适配器系统
### 支持的存储类型
1. **本地存储 (Local)** - 文件存储在本地文件系统
2. **S3 存储 (S3)** - 文件存储在 AWS S3 或兼容的对象存储服务
### 环境变量配置
#### 本地存储配置
```bash
STORAGE_TYPE=local
UPLOAD_DIR=./uploads
UPLOAD_EXPIRATION_MS=0 # 0 表示不自动过期(推荐设置)
```
#### S3 存储配置
```bash
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表示文件不会自动过期
- **手动清理**: 提供多种手动清理选项
- **灵活控制**: 可根据需要设置过期时间,或完全禁用自动清理
### 无感切换机制
1. **单例模式管理**: `StorageManager` 使用单例模式确保全局一致性
2. **自动配置检测**: 启动时根据环境变量自动选择存储类型
3. **统一接口**: 所有存储类型都实现相同的 TUS `DataStore` 接口
4. **运行时切换**: 支持运行时切换存储配置(需要重启生效)
## 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 使用示例
### 获取存储类型统计
```javascript
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 }
// }
```
### 查询特定存储类型的资源
```javascript
const response = await fetch('/api/upload/resources/storage/s3');
const s3Resources = await response.json();
```
### 迁移存储类型标记
```javascript
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 }
```
### 手动清理特定状态的资源
```javascript
const response = await fetch('/api/upload/cleanup/by-status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
status: 'UPLOADING',
olderThanDays: 7,
}),
});
```
## 🆕 存储管理示例
### 获取存储信息
```javascript
const response = await fetch('/api/upload/storage/info');
const storageInfo = await response.json();
// { type: 'local', config: { directory: './uploads' } }
```
### 切换到 S3 存储
```javascript
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),
});
```
### 验证存储配置
```javascript
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' }
```
## 特性保留
1. **TUS 协议支持** - 完全保留原有的断点续传功能
2. **文件命名** - 保留安全的文件命名策略
3. **资源状态管理** - 保留完整的上传状态跟踪
4. **自动清理** - 保留过期文件清理功能(默认禁用)
5. **数据库集成** - 保留 Prisma ORM 数据库操作
## 🆕 新增特性
1. **多存储后端支持** - 支持本地存储和 S3 存储
2. **无感切换** - 运行时可切换存储类型
3. **配置验证** - 提供存储配置验证功能
4. **存储信息查询** - 可查询当前存储配置
5. **统一日志** - 存储操作统一日志记录
6. **🆕 存储类型记录** - 数据库记录每个资源的存储类型
7. **🆕 灵活清理** - 支持按状态、时间等条件清理
8. **🆕 统计分析** - 提供详细的资源统计信息
9. **🆕 不过期设置** - 默认不自动过期,避免意外删除
## 运行
服务启动时会自动:
1. 根据环境变量初始化存储适配器
2. 初始化 TUS 服务器
3. 注册 REST API 路由
4. 启动定时清理任务(如果启用)
支持的存储切换场景:
- 开发环境使用本地存储
- 生产环境使用 S3 存储
- 混合云部署灵活切换
- 存储迁移时批量更新资源标记
## 💡 最佳实践
1. **过期设置**: 推荐设置 `UPLOAD_EXPIRATION_MS=0` 避免文件意外过期
2. **存储记录**: 利用数据库中的 `storageType` 字段追踪文件位置
3. **定期清理**: 使用手动清理 API 定期清理不需要的资源
4. **监控统计**: 使用统计 API 监控存储使用情况
5. **迁移策略**: 在存储迁移时先更新环境变量,再使用迁移 API 更新数据库标记
无需代码修改,仅通过环境变量即可实现存储后端的无感切换。