fenghuo/packages/storage/README.md

325 lines
8.9 KiB
Markdown
Raw Normal View History

2025-05-28 20:00:36 +08:00
# @repo/storage
一个完全兼容 Hono 的存储解决方案,支持本地存储和 S3 兼容存储,提供 TUS 协议上传、文件管理和 REST API。
## 特性
- 🚀 **多存储支持**: 支持本地文件系统和 S3 兼容存储
- 📤 **TUS 协议**: 支持可恢复的文件上传
- 🔧 **Hono 集成**: 提供开箱即用的 Hono 中间件
- 📊 **文件管理**: 完整的文件生命周期管理
- 🗄️ **数据库集成**: 与 Prisma 深度集成
-**自动清理**: 支持过期文件自动清理
- 🔄 **存储迁移**: 支持不同存储类型间的数据迁移
## 安装
```bash
npm install @repo/storage
```
## 环境变量配置
### 基础配置
| 变量名 | 类型 | 默认值 | 描述 |
| ---------------------- | --------------- | ------- | ------------------------------------- |
| `STORAGE_TYPE` | `local` \| `s3` | `local` | 存储类型选择 |
| `UPLOAD_EXPIRATION_MS` | `number` | `0` | 上传文件过期时间毫秒0表示不过期 |
### 本地存储配置
`STORAGE_TYPE=local` 时需要配置:
| 变量名 | 类型 | 默认值 | 描述 |
| ------------ | -------- | ----------- | ---------------- |
| `UPLOAD_DIR` | `string` | `./uploads` | 本地存储目录路径 |
### S3 存储配置
`STORAGE_TYPE=s3` 时需要配置:
| 变量名 | 类型 | 默认值 | 描述 | 必需 |
| --------------------------- | --------- | ----------- | ---------------------------------- | ---- |
| `S3_BUCKET` | `string` | - | S3 存储桶名称 | ✅ |
| `S3_REGION` | `string` | `us-east-1` | S3 区域 | ✅ |
| `S3_ACCESS_KEY_ID` | `string` | - | S3 访问密钥 ID | ✅ |
| `S3_SECRET_ACCESS_KEY` | `string` | - | S3 访问密钥 | ✅ |
| `S3_ENDPOINT` | `string` | - | 自定义 S3 端点(用于兼容其他服务) | ❌ |
| `S3_FORCE_PATH_STYLE` | `boolean` | `false` | 是否强制使用路径样式 | ❌ |
| `S3_PART_SIZE` | `number` | `8388608` | 分片上传大小8MB | ❌ |
| `S3_MAX_CONCURRENT_UPLOADS` | `number` | `60` | 最大并发上传数 | ❌ |
## 配置示例
### 本地存储配置
```bash
# .env
STORAGE_TYPE=local
UPLOAD_DIR=./uploads
UPLOAD_EXPIRATION_MS=86400000 # 24小时过期
```
### AWS S3 配置
```bash
# .env
STORAGE_TYPE=s3
S3_BUCKET=my-app-uploads
S3_REGION=us-west-2
S3_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
S3_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
UPLOAD_EXPIRATION_MS=604800000 # 7天过期
```
### MinIO 配置
```bash
# .env
STORAGE_TYPE=s3
S3_BUCKET=uploads
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=minioadmin
S3_SECRET_ACCESS_KEY=minioadmin
S3_ENDPOINT=http://localhost:9000
S3_FORCE_PATH_STYLE=true
```
### 阿里云 OSS 配置
```bash
# .env
STORAGE_TYPE=s3
S3_BUCKET=my-oss-bucket
S3_REGION=oss-cn-hangzhou
S3_ACCESS_KEY_ID=your-access-key-id
S3_SECRET_ACCESS_KEY=your-access-key-secret
S3_ENDPOINT=https://oss-cn-hangzhou.aliyuncs.com
S3_FORCE_PATH_STYLE=false
```
### 腾讯云 COS 配置
```bash
# .env
STORAGE_TYPE=s3
S3_BUCKET=my-cos-bucket-1234567890
S3_REGION=ap-beijing
S3_ACCESS_KEY_ID=your-secret-id
S3_SECRET_ACCESS_KEY=your-secret-key
S3_ENDPOINT=https://cos.ap-beijing.myqcloud.com
S3_FORCE_PATH_STYLE=false
```
## 快速开始
### 1. 基础使用
```typescript
import { createStorageApp, startCleanupScheduler } from '@repo/storage';
import { Hono } from 'hono';
const app = new Hono();
// 创建存储应用
const storageApp = createStorageApp({
apiBasePath: '/api/storage', // API 路径
uploadPath: '/upload', // 上传路径
});
// 挂载存储应用
app.route('/', storageApp);
// 启动清理调度器
startCleanupScheduler();
```
### 2. 分别使用 API 和上传功能
```typescript
import { createStorageRoutes, createTusUploadRoutes } from '@repo/storage';
const app = new Hono();
// 只添加存储管理 API
app.route('/api/storage', createStorageRoutes());
// 只添加文件上传功能
app.route('/upload', createTusUploadRoutes());
```
### 3. 使用存储管理器
```typescript
import { StorageManager, StorageUtils } from '@repo/storage';
// 获取存储管理器实例
const storageManager = StorageManager.getInstance();
// 获取存储信息
const storageInfo = storageManager.getStorageInfo();
console.log('当前存储类型:', storageInfo.type);
// 使用存储工具
const storageUtils = StorageUtils.getInstance();
// 生成文件访问 URL统一使用下载接口
const fileUrl = storageUtils.generateFileUrl('2024/01/01/abc123/file.jpg');
// 结果: http://localhost:3000/download/2024/01/01/abc123/file.jpg
// 生成完整的公开访问 URL
const publicUrl = storageUtils.generateFileUrl('2024/01/01/abc123/file.jpg', 'https://yourdomain.com');
// 结果: https://yourdomain.com/download/2024/01/01/abc123/file.jpg
// 生成 S3 直接访问 URL仅 S3 存储)
try {
const directUrl = storageUtils.generateDirectUrl('2024/01/01/abc123/file.jpg');
// S3 存储: https://bucket.s3.region.amazonaws.com/2024/01/01/abc123/file.jpg
} catch (error) {
// 本地存储会抛出错误
}
// 检查文件是否存在
const exists = await storageUtils.fileExists('file-id');
```
### 4. 分别配置不同功能
```typescript
import { createStorageRoutes, createTusUploadRoutes, createFileDownloadRoutes } from '@repo/storage';
const app = new Hono();
// 只添加存储管理 API
app.route('/api/storage', createStorageRoutes());
// 只添加文件上传功能
app.route('/upload', createTusUploadRoutes());
// 只添加文件下载功能(所有存储类型)
app.route('/download', createFileDownloadRoutes());
```
## API 端点
### 文件资源管理
- `GET /api/storage/resource/:fileId` - 获取文件资源信息
- `GET /api/storage/resources` - 获取所有资源
- `GET /api/storage/resources/storage/:storageType` - 按存储类型获取资源
- `GET /api/storage/resources/status/:status` - 按状态获取资源
- `GET /api/storage/resources/uploading` - 获取正在上传的资源
- `DELETE /api/storage/resource/:id` - 删除资源
- `PATCH /api/storage/resource/:id` - 更新资源
### 文件访问和下载
- `GET /download/:fileId` - 文件下载和访问(支持所有存储类型)
### 统计和管理
- `GET /api/storage/stats` - 获取资源统计信息
- `POST /api/storage/cleanup` - 手动清理过期上传
- `POST /api/storage/cleanup/by-status` - 按状态清理资源
- `POST /api/storage/migrate-storage` - 迁移存储类型
### 存储配置
- `GET /api/storage/storage/info` - 获取存储信息
- `POST /api/storage/storage/switch` - 切换存储配置
- `POST /api/storage/storage/validate` - 验证存储配置
### 文件上传
- `POST /upload` - TUS 协议文件上传
- `PATCH /upload/:id` - 续传文件
- `HEAD /upload/:id` - 获取上传状态
## 数据库操作
```typescript
import {
getAllResources,
getResourceByFileId,
createResource,
updateResourceStatus,
deleteResource,
} from '@repo/storage';
// 获取所有资源
const resources = await getAllResources();
// 根据文件ID获取资源
const { status, resource } = await getResourceByFileId('file-id');
// 创建新资源
const newResource = await createResource({
fileId: 'unique-file-id',
filename: 'example.jpg',
size: 1024000,
mimeType: 'image/jpeg',
storageType: 'local',
});
```
## 文件生命周期
1. **上传开始**: 创建资源记录,状态为 `UPLOADING`
2. **上传完成**: 状态更新为 `UPLOADED`
3. **处理中**: 状态可更新为 `PROCESSING`
4. **处理完成**: 状态更新为 `PROCESSED`
5. **清理**: 过期文件自动清理
## 存储迁移
支持在不同存储类型之间迁移数据:
```bash
# API 调用示例
curl -X POST http://localhost:3000/api/storage/migrate-storage \
-H "Content-Type: application/json" \
-d '{"from": "local", "to": "s3"}'
```
## 安全考虑
1. **环境变量**: 敏感信息(如 S3 密钥)应存储在环境变量中
2. **访问控制**: 建议在生产环境中添加适当的身份验证
3. **CORS 配置**: 根据需要配置跨域访问策略
4. **文件验证**: 建议添加文件类型和大小验证
## 故障排除
### 常见问题
1. **找不到模块错误**: 确保已正确安装依赖包
2. **S3 连接失败**: 检查网络连接和凭据配置
3. **本地存储权限**: 确保应用有写入本地目录的权限
4. **上传失败**: 检查文件大小限制和存储空间
### 调试模式
启用详细日志:
```bash
DEBUG=storage:* npm start
```
## 许可证
MIT License
## 贡献
欢迎提交 Issue 和 Pull Request
## 更新日志
### v2.0.0
- 重构为模块化架构
- 添加完整的 TypeScript 支持
- 支持多种 S3 兼容服务
- 改进的错误处理和日志记录