# 材质上传与管理 **本文档引用的文件** - [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) ## 目录 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
统计用户上传数量"] Count --> Compare{"当前数量 >= 最大限制?"} Compare --> |是| ReturnError["返回错误信息:
已达到最大上传数量限制"] 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
获取材质信息"] GetTexture --> CheckExist{"材质存在?"} CheckExist --> |否| ReturnError1["返回错误:
材质不存在"] CheckExist --> |是| CheckPermission{"UploaderID匹配?"} CheckPermission --> |否| ReturnError2["返回错误:
无权修改此材质"] 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
更新数据库"] 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)