feat: 添加环境变量管理工具和部署配置改版
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m33s

主要改动:
- 新增交互式环境配置脚本 (scripts/setup-env.sh)
- 新增本地启动快捷脚本 (scripts/run-local.sh)
- 新增环境变量模板文件 (.env.example)
- 部署模式改版:使用嵌入式配置 + 环境变量覆盖
- 添加对象存储功能支持
- 改进 IoT 卡片导入任务
- 优化 OpenAPI 文档生成
- 删除旧的配置文件,改用嵌入式默认配置
This commit is contained in:
2026-01-26 10:28:29 +08:00
parent 194078674a
commit 45aa7deb87
94 changed files with 6532 additions and 1967 deletions

View File

@@ -0,0 +1,163 @@
# 对象存储使用指南
本文档介绍如何在后端代码中使用对象存储服务。
## 配置
通过环境变量配置对象存储:
```bash
# 存储提供商
export JUNHONG_STORAGE_PROVIDER="s3"
# S3 配置
export JUNHONG_STORAGE_S3_ENDPOINT="http://obs-helf.cucloud.cn"
export JUNHONG_STORAGE_S3_REGION="cn-langfang-2"
export JUNHONG_STORAGE_S3_BUCKET="cmp"
export JUNHONG_STORAGE_S3_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export JUNHONG_STORAGE_S3_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export JUNHONG_STORAGE_S3_USE_SSL="false"
export JUNHONG_STORAGE_S3_PATH_STYLE="true"
# 预签名 URL 配置
export JUNHONG_STORAGE_PRESIGN_UPLOAD_EXPIRES="15m"
export JUNHONG_STORAGE_PRESIGN_DOWNLOAD_EXPIRES="24h"
# 临时文件目录
export JUNHONG_STORAGE_TEMP_DIR="/tmp/junhong-storage"
```
详细配置说明见 [环境变量配置文档](../environment-variables.md)
## StorageService 使用
### 获取预签名上传 URL
```go
result, err := storageService.GetUploadURL(ctx, "iot_import", "cards.csv", "text/csv")
if err != nil {
return err
}
// result.URL - 预签名上传 URL
// result.FileKey - 文件路径(用于后续业务接口)
// result.ExpiresIn - URL 有效期(秒)
```
### 下载文件到临时目录
```go
localPath, cleanup, err := storageService.DownloadToTemp(ctx, fileKey)
if err != nil {
return err
}
defer cleanup() // 处理完成后自动删除临时文件
// 使用 localPath 读取文件内容
f, _ := os.Open(localPath)
defer f.Close()
```
### 直接上传文件
```go
reader := bytes.NewReader(content)
err := storageService.Provider().Upload(ctx, fileKey, reader, "text/csv")
```
### 检查文件是否存在
```go
exists, err := storageService.Provider().Exists(ctx, fileKey)
```
### 删除文件
```go
err := storageService.Provider().Delete(ctx, fileKey)
```
## Purpose 类型
| Purpose | 说明 | 生成路径 | ContentType |
|---------|------|---------|-------------|
| iot_import | ICCID 导入 | imports/YYYY/MM/DD/uuid.csv | text/csv |
| export | 数据导出 | exports/YYYY/MM/DD/uuid.xlsx | application/vnd.openxmlformats... |
| attachment | 附件上传 | attachments/YYYY/MM/DD/uuid.ext | 自动检测 |
## 错误处理
存储相关错误码定义在 `pkg/errors/codes.go`
| 错误码 | 说明 |
|-------|------|
| 1090 | 对象存储服务未配置 |
| 1091 | 文件上传失败 |
| 1092 | 文件下载失败 |
| 1093 | 文件不存在 |
| 1094 | 不支持的文件用途 |
| 1095 | 不支持的文件类型 |
## 在 Handler 中使用
```go
type MyHandler struct {
storageService *storage.Service
}
func (h *MyHandler) Upload(c *fiber.Ctx) error {
var req dto.GetUploadURLRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam, "参数解析失败")
}
result, err := h.storageService.GetUploadURL(
c.UserContext(),
req.Purpose,
req.FileName,
req.ContentType,
)
if err != nil {
return errors.New(errors.CodeStorageUploadFailed, err.Error())
}
return response.Success(c, result)
}
```
## 在 Worker 中使用
```go
func (h *TaskHandler) HandleTask(ctx context.Context, task *asynq.Task) error {
// 从任务记录获取文件路径
fileKey := importTask.StorageKey
// 下载到临时文件
localPath, cleanup, err := h.storageService.DownloadToTemp(ctx, fileKey)
if err != nil {
return err
}
defer cleanup()
// 解析文件
f, _ := os.Open(localPath)
defer f.Close()
// 处理文件内容...
}
```
## 测试验证
运行对象存储功能测试:
```bash
go run scripts/test_storage.go
```
测试内容包括:
1. 生成预签名上传 URL
2. 上传测试文件
3. 检查文件是否存在
4. 下载到临时文件
5. 删除测试文件