feat: 实现 SimApiStorage(S3/MinIO 存储)

- 自实现 AWS Signature V4(HMAC-SHA256 基于 stdx SHA256),无需 Minio SDK
- getUploadUrl / getDownloadUrl(预签名 PUT/GET)
- uploadFile(直接 PUT 上传)、fullUrl / getUrl / getPath
- 构造时检测并自动创建桶(静态守卫只执行一次)
- 注册为 Scoped 以注入 IHttpContextAccessor(soulsoft DI 禁止 singleton 消费 scoped)
- 签名核心已用 AWS 官方测试向量验证(最终签名 5d672d79... 一致)
- README 同步(未实现表移除、新增 5.3 存储章节)
This commit is contained in:
2026-08-17 00:00:15 +08:00
parent 92eea3108a
commit eb488bcd5a
3 changed files with 490 additions and 4 deletions
+32 -3
View File
@@ -82,7 +82,8 @@ simapi-cj/
│ ├── exceptions/ # SimApiException
│ ├── extensions/ # SimApiExtensionsaddSimApi / useSimApi + 内置路由 + 响应封装)
│ ├── helpers/ # SimApiError, SimApiUtil, SimApiAuth, SimApiCache, SimApiHttpClient,
│ │ # SimApiAesUtil(AES-256), SimApiSignChecker(验签), SimApiAesBodyChecker(AES body)
│ │ # SimApiAesUtil(AES-256), SimApiSignChecker(验签), SimApiAesBodyChecker(AES body),
│ │ # SimApiStorage(S3/MinIO, 自实现 SigV4)
│ ├── interfaces/ # ISimApiAuthChecker
│ ├── logger/ # SimApiLogger, SimApiLoggerProvider(彩色日志)
│ ├── macros/ # ReadTomlVersion(编译期读版本号)
@@ -320,6 +321,35 @@ builder.addSimApi { options =>
| Fatal | 深红(DarkRed 粗体近似) |
| 其他 | 白(White |
### 5.3 存储 — SimApiStorageS3/MinIO,对齐 C# SimApiStorage
`enableSimApiStorage = true` 时注册 `SimApiStorage`Scoped,内部自实现 AWS Signature V4,无需 Minio SDK):
```cangjie
builder.addSimApi { options =>
options.enableSimApiStorage = true
options.configureSimApiStorage { storage =>
storage.endpoint = "http://192.168.0.2:9000" // 必须 http:// 或 https:// 开头
storage.serveUrl = "https://files.example.com" // 文件访问地址,不能以 / 结尾
storage.bucket = "app-files"
storage.accessKey = "minioadmin"
storage.secretKey = "minioadmin"
}
}
```
| 方法 | 说明 |
|------|------|
| `getUploadUrl(path, expire=7200)` | 上传预签名 URL,返回 `GetUploadUrlResponse(UploadUrl, DownloadUrl, Path)` |
| `getDownloadUrl(path, expire=600)` | 下载预签名 URL |
| `uploadFile(path, data, contentType="image/png")` | 直接 PUT 上传(字节数组) |
| `fullUrl(path)` / `getUrl(path)` | 补全访问 URL`~/` 前缀依赖请求上下文) |
| `getPath(url)` | 从 URL 还原相对路径(去掉 Endpoint/Bucket 或 ServeUrl 前缀) |
> 说明:桶不存在时自动创建(对齐 C# BucketExists + MakeBucket,静态守卫只执行一次);
> 预签名与上传使用 AWS SigV4HMAC-SHA256 基于 stdx SHA256 自实现),已用 AWS 官方测试向量验证签名正确。
> 注册为 Scoped 是为了注入 `IHttpContextAccessor`soulsoft DI 禁止 singleton 消费 scoped 服务)。
### 6. 内置路由(UseSimApi 自动注册)
| 路由 | 方法 | 条件 | 说明 |
@@ -465,11 +495,10 @@ public class MyController <: SimApiBaseController {
| 选项 | 原功能 | 状态 |
|------|--------|------|
| `enableSimApiDoc` | Swagger 文档(可换 soulsoft_web_openapi | ❌ 未实现 |
| `enableSimApiStorage` | S3/MinIO 存储 | ❌ 未实现 |
| `enableSynapse` | MQTT 通信 | ❌ 未实现 |
| `enableJob` | Hangfire 任务调度 | ❌ 未实现 |
> ✅ 已实现(曾为占位):`enableSimApiAuthGate`AuthSDK 认证中心)、`SimApiAesUtil`(纯仓颉 AES-256-CBC,与 .NET 双向互操作)、`ISimApiAuthChecker`(注解鉴权时执行)、内置路由自定义路径。
> ✅ 已实现(曾为占位):`enableSimApiStorage`S3/MinIO,自实现 AWS SigV4)、`enableSimApiAuthGate`AuthSDK 认证中心)、`SimApiAesUtil`(纯仓颉 AES-256-CBC,与 .NET 双向互操作)、`ISimApiAuthChecker`(注解鉴权时执行)、内置路由自定义路径。
---