Files
backend/.qoder/repowiki/zh/content/API参考/材质API/材质上传与管理/材质上传与管理.md

145 lines
8.5 KiB
Markdown
Raw Normal View History

# 材质上传与管理
<cite>
**本文档引用的文件**
- [texture_service.go](file://internal/service/texture_service.go)
- [upload_service.go](file://internal/service/upload_service.go)
- [texture_repository.go](file://internal/repository/texture_repository.go)
- [texture.go](file://internal/model/texture.go)
- [routes.go](file://internal/handler/routes.go)
</cite>
## 目录
1. [简介](#简介)
2. [上传流程与元数据创建](#上传流程与元数据创建)
3. [上传限制检查机制](#上传限制检查机制)
4. [材质更新API权限控制](#材质更新api权限控制)
5. [字段更新策略](#字段更新策略)
6. [错误处理场景](#错误处理场景)
## 简介
本系统提供完整的材质上传与管理功能支持用户上传皮肤SKIN和披风CAPE材质。系统通过预签名URL实现安全的文件上传确保只有经过身份验证的用户才能上传和管理自己的材质。材质元数据存储在数据库中包含名称、描述、类型、哈希值等信息。系统实现了严格的权限控制确保只有上传者才能修改或删除自己的材质。同时系统还提供了收藏、下载统计等功能增强了用户体验。
## 上传流程与元数据创建
材质上传流程分为两个阶段生成上传URL和创建材质元数据。首先用户通过调用`/api/v1/texture/upload-url`接口获取预签名的上传URL。该接口验证用户身份、文件名和材质类型后生成一个临时的上传链接允许用户直接上传文件到存储服务。上传完成后用户调用`/api/v1/texture`接口创建材质元数据。系统会验证用户是否存在、材质哈希是否重复并创建相应的数据库记录。材质元数据包括上传者ID、名称、描述、类型、URL、哈希值、大小、公开状态等信息。
```mermaid
sequenceDiagram
participant 用户 as 用户
participant 处理器 as texture_handler
participant 服务 as upload_service
participant 存储 as 存储服务
用户->>处理器 : POST /api/v1/texture/upload-url
处理器->>服务 : GenerateTextureUploadURL()
服务->>服务 : 验证文件名和类型
服务->>存储 : 生成预签名POST URL
存储-->>服务 : 返回预签名URL
服务-->>处理器 : 返回URL
处理器-->>用户 : 返回上传URL
用户->>存储 : 使用预签名URL上传文件
存储-->>用户 : 上传成功
用户->>处理器 : POST /api/v1/texture
处理器->>服务 : CreateTexture()
服务->>服务 : 验证用户和哈希
服务->>repository : CreateTexture()
repository-->>服务 : 创建成功
服务-->>处理器 : 返回材质信息
处理器-->>用户 : 返回创建结果
```
**图示来源**
- [upload_service.go](file://internal/service/upload_service.go#L117-L160)
- [texture_service.go](file://internal/service/texture_service.go#L12-L63)
- [routes.go](file://internal/handler/routes.go#L53-L54)
**本节来源**
- [upload_service.go](file://internal/service/upload_service.go#L117-L160)
- [texture_service.go](file://internal/service/texture_service.go#L12-L63)
## 上传限制检查机制
系统通过`CheckTextureUploadLimit`函数实现用户上传数量限制。该函数接收数据库连接、上传者ID和最大允许上传数量作为参数。首先函数调用`CountTexturesByUploaderID`从数据库中统计指定用户已上传的材质数量。然后将统计结果与最大限制进行比较。如果当前上传数量大于或等于最大限制函数返回错误信息提示用户已达到最大上传数量限制。否则函数返回nil表示可以继续上传。系统配置中定义了每个用户的最大材质数量限制默认值为100。
```mermaid
flowchart TD
Start([开始]) --> Count["调用CountTexturesByUploaderID<br/>统计用户上传数量"]
Count --> Compare{"当前数量 >= 最大限制?"}
Compare --> |是| ReturnError["返回错误信息:<br/>已达到最大上传数量限制"]
Compare --> |否| ReturnSuccess["返回nil允许上传"]
ReturnError --> End([结束])
ReturnSuccess --> End
```
**图示来源**
- [texture_service.go](file://internal/service/texture_service.go#L239-L251)
- [texture_repository.go](file://internal/repository/texture_repository.go#L223-L231)
**本节来源**
- [texture_service.go](file://internal/service/texture_service.go#L239-L251)
## 材质更新API权限控制
材质更新API实现了严格的权限控制确保只有上传者才能修改自己的材质。当用户尝试更新材质时系统首先通过`FindTextureByID`从数据库中获取材质信息。然后比较请求中的上传者ID与材质记录中的`UploaderID`。如果两者不匹配,系统返回"无权修改此材质"的错误信息。这种基于上传者ID的权限检查机制有效防止了未经授权的修改操作。权限检查在`UpdateTexture`服务函数中实现,是更新操作的第一步,确保在进行任何数据修改之前完成身份验证。
```mermaid
flowchart TD
Start([开始]) --> GetTexture["调用FindTextureByID<br/>获取材质信息"]
GetTexture --> CheckExist{"材质存在?"}
CheckExist --> |否| ReturnError1["返回错误:<br/>材质不存在"]
CheckExist --> |是| CheckPermission{"UploaderID匹配?"}
CheckPermission --> |否| ReturnError2["返回错误:<br/>无权修改此材质"]
CheckPermission --> |是| UpdateFields["更新指定字段"]
UpdateFields --> ReturnSuccess["返回更新后的材质"]
ReturnError1 --> End([结束])
ReturnError2 --> End
ReturnSuccess --> End
```
**图示来源**
- [texture_service.go](file://internal/service/texture_service.go#L106-L141)
- [texture_repository.go](file://internal/repository/texture_repository.go#L16-L27)
**本节来源**
- [texture_service.go](file://internal/service/texture_service.go#L106-L141)
## 字段更新策略
系统采用灵活的字段更新策略,仅更新客户端提供的字段。当更新材质时,系统创建一个`updates`映射来存储需要更新的字段。如果提供了名称且不为空,将其添加到`updates`映射中;如果提供了描述且不为空,也将其添加到映射中;如果提供了公开状态(`isPublic`),同样将其添加到映射中。只有当`updates`映射不为空时,系统才会调用`UpdateTextureFields`执行数据库更新操作。这种策略避免了不必要的数据库写入,提高了性能,并确保未提供的字段保持原值不变。
```mermaid
flowchart TD
Start([开始]) --> InitMap["初始化updates映射"]
InitMap --> CheckName{"名称提供且不为空?"}
CheckName --> |是| AddName["添加name到updates映射"]
CheckName --> |否| CheckDesc
AddName --> CheckDesc
CheckDesc --> {"描述提供且不为空?"}
CheckDesc --> |是| AddDesc["添加description到updates映射"]
CheckDesc --> |否| CheckPublic
AddDesc --> CheckPublic
CheckPublic --> {"公开状态提供?"}
CheckPublic --> |是| AddPublic["添加is_public到updates映射"]
CheckPublic --> |否| CheckUpdates
AddPublic --> CheckUpdates
CheckUpdates --> {"updates映射为空?"}
CheckUpdates --> |是| ReturnOriginal["返回原材质"]
CheckUpdates --> |否| UpdateDB["调用UpdateTextureFields<br/>更新数据库"]
UpdateDB --> ReturnUpdated["返回更新后的材质"]
ReturnOriginal --> End([结束])
ReturnUpdated --> End
```
**图示来源**
- [texture_service.go](file://internal/service/texture_service.go#L106-L141)
- [texture_repository.go](file://internal/repository/texture_repository.go#L120-L124)
**本节来源**
- [texture_service.go](file://internal/service/texture_service.go#L106-L141)
## 错误处理场景
系统在材质上传与管理过程中实现了全面的错误处理机制。当用户达到上传上限时,`CheckTextureUploadLimit`函数返回"已达到最大上传数量限制"的错误信息。当用户尝试修改不属于自己的材质时,`UpdateTexture`函数返回"无权修改此材质"的错误信息。其他常见错误包括:用户不存在、材质已存在、无效的材质类型、文件名为空、不支持的文件格式等。所有错误都通过标准的错误响应格式返回给客户端,包含错误代码和描述信息,便于前端进行相应的错误处理和用户提示。
**本节来源**
- [texture_service.go](file://internal/service/texture_service.go#L239-L251)
- [texture_service.go](file://internal/service/texture_service.go#L106-L141)
- [upload_service.go](file://internal/service/upload_service.go#L120-L127)
- [texture_service.go](file://internal/service/texture_service.go#L19-L21)
- [texture_service.go](file://internal/service/texture_service.go#L28-L30)
- [texture_service.go](file://internal/service/texture_service.go#L40-L41)