# 通用对象存储能力 ## Why 当前 ICCID 导入功能通过后端接收上传文件,占用服务器带宽和内存,大文件处理效率低。同时,未来的导出功能也需要文件存储能力。需要接入联通云对象存储(S3 兼容),采用预签名 URL 方案实现前端直传,提升性能和安全性。 此外,本项目作为公司后端模板项目,对象存储应设计为通用能力,方便复用到其他系统。 ## What Changes - **新增通用对象存储包**:`pkg/storage/` 提供 S3 兼容的对象存储能力 - 支持上传、下载、删除、检查存在性 - 支持生成预签名上传/下载 URL - 可扩展支持多云(阿里云、腾讯云等,仅需更换 Endpoint) - **新增存储 API 接口**:供前端获取预签名上传 URL - `POST /api/admin/storage/upload-url`:获取上传预签名 URL - **改造 ICCID 导入流程**: - 移除原有的文件上传处理(`c.FormFile`) - 改为接收 `file_key` 参数(对象存储路径) - Worker 从对象存储下载文件后处理 - 处理完成后删除本地临时文件 - **数据模型变更**: - `IotCardImportTask` 新增 `storage_bucket`、`storage_key` 字段 - 需要数据库迁移 - **配置结构扩展**: - 新增 `storage` 配置块(endpoint、region、bucket、credentials) ## Capabilities ### New Capabilities - `object-storage`: 通用对象存储能力,提供 S3 兼容的文件上传、下载、删除、预签名 URL 生成功能 ### Modified Capabilities - `iot-card-import`: ICCID 导入流程改造,从直接上传改为对象存储集成 ## Impact ### 代码变更 | 层级 | 变更内容 | |------|----------| | `pkg/storage/` | 新增:Provider 接口、S3 实现、配置类型 | | `pkg/config/` | 修改:新增 StorageConfig 结构 | | `configs/` | 修改:新增 storage 配置块 | | `internal/bootstrap/` | 修改:初始化 Storage Provider | | `internal/handler/admin/` | 新增:StorageHandler(获取上传 URL)| | `internal/handler/admin/` | 修改:IotCardImportHandler(移除文件上传)| | `internal/service/iot_card_import/` | 修改:接收 file_key 而非文件流 | | `internal/task/` | 修改:从对象存储下载文件处理 | | `internal/model/` | 修改:IotCardImportTask 新增字段 | | `internal/routes/` | 修改:新增 storage 路由 | | `migrations/` | 新增:添加 storage 字段迁移 | ### API 变更 | 接口 | 变更类型 | 说明 | |------|----------|------| | `POST /api/admin/storage/upload-url` | 新增 | 获取预签名上传 URL | | `POST /api/admin/iot-cards/import` | **BREAKING** | 移除文件上传,改为传 file_key | ### 依赖变更 | 依赖 | 说明 | |------|------| | `github.com/aws/aws-sdk-go` | 新增:AWS S3 兼容 SDK(已验证联通云支持) | ### 配置变更 ```yaml storage: provider: "s3" s3: endpoint: "http://obs-helf.cucloud.cn" region: "cn-langfang-2" bucket: "cmp" access_key_id: "${OSS_ACCESS_KEY_ID}" secret_access_key: "${OSS_SECRET_ACCESS_KEY}" use_ssl: false path_style: true presign: upload_expires: "15m" # 上传预签名有效期 download_expires: "24h" # 下载预签名有效期 temp_dir: "/tmp/junhong-storage" # 临时文件目录 ``` ### 前端适配 前端需要配合修改上传流程: 1. 先调用 `POST /api/admin/storage/upload-url` 获取预签名 URL 2. 直接 PUT 到预签名 URL 上传文件 3. 上传成功后调用导入接口,传入 `file_key`