# 对象存储使用指南 本文档介绍如何在后端代码中使用对象存储服务。 ## 配置 通过环境变量配置对象存储: ```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. 删除测试文件