All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m33s
主要改动: - 新增交互式环境配置脚本 (scripts/setup-env.sh) - 新增本地启动快捷脚本 (scripts/run-local.sh) - 新增环境变量模板文件 (.env.example) - 部署模式改版:使用嵌入式配置 + 环境变量覆盖 - 添加对象存储功能支持 - 改进 IoT 卡片导入任务 - 优化 OpenAPI 文档生成 - 删除旧的配置文件,改用嵌入式默认配置
3.7 KiB
3.7 KiB
对象存储使用指南
本文档介绍如何在后端代码中使用对象存储服务。
配置
通过环境变量配置对象存储:
# 存储提供商
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"
详细配置说明见 环境变量配置文档
StorageService 使用
获取预签名上传 URL
result, err := storageService.GetUploadURL(ctx, "iot_import", "cards.csv", "text/csv")
if err != nil {
return err
}
// result.URL - 预签名上传 URL
// result.FileKey - 文件路径(用于后续业务接口)
// result.ExpiresIn - URL 有效期(秒)
下载文件到临时目录
localPath, cleanup, err := storageService.DownloadToTemp(ctx, fileKey)
if err != nil {
return err
}
defer cleanup() // 处理完成后自动删除临时文件
// 使用 localPath 读取文件内容
f, _ := os.Open(localPath)
defer f.Close()
直接上传文件
reader := bytes.NewReader(content)
err := storageService.Provider().Upload(ctx, fileKey, reader, "text/csv")
检查文件是否存在
exists, err := storageService.Provider().Exists(ctx, fileKey)
删除文件
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 中使用
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 中使用
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()
// 处理文件内容...
}
测试验证
运行对象存储功能测试:
go run scripts/test_storage.go
测试内容包括:
- 生成预签名上传 URL
- 上传测试文件
- 检查文件是否存在
- 下载到临时文件
- 删除测试文件