From a95a2852d4e57778a9b73c54ae6b60f261d0ba12 Mon Sep 17 00:00:00 2001 From: zpc Date: Wed, 28 Jan 2026 14:33:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E4=B8=8A=E4=BC=A0=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81Base64=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E5=88=B0=E8=85=BE=E8=AE=AF=E4=BA=91COS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 updateUserInfo 接口路由(update_userinfo -> updateUserInfo) - IUploadService 添加 UploadBase64ImageAsync 方法 - UploadService 实现 Base64 图片解析和 COS 上传 - UserController 注入 IUploadService 替代本地保存逻辑 - HoneyBox.Api 添加对 HoneyBox.Admin.Business 的项目引用 --- .../Services/Interfaces/IUploadService.cs | 8 ++ .../Services/UploadService.cs | 89 +++++++++++++++++++ .../Controllers/UserController.cs | 57 +++--------- .../src/HoneyBox.Api/HoneyBox.Api.csproj | 1 + 4 files changed, 108 insertions(+), 47 deletions(-) diff --git a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUploadService.cs b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUploadService.cs index 9a774f7e..57431611 100644 --- a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUploadService.cs +++ b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/Interfaces/IUploadService.cs @@ -22,6 +22,14 @@ public interface IUploadService /// 上传响应列表 Task> UploadImagesAsync(List files); + /// + /// 上传Base64编码的图片 + /// + /// Base64编码的图片数据(可包含data:image/xxx;base64,前缀) + /// 文件名前缀,如 "avatar" + /// 上传后的图片URL,失败返回null + Task UploadBase64ImageAsync(string base64Image, string fileNamePrefix = "image"); + /// /// 获取预签名上传URL(客户端直传) /// diff --git a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UploadService.cs b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UploadService.cs index d5dd1aca..7380112f 100644 --- a/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UploadService.cs +++ b/server/HoneyBox/src/HoneyBox.Admin.Business/Services/UploadService.cs @@ -101,6 +101,95 @@ public class UploadService : IUploadService return results; } + /// + public async Task UploadBase64ImageAsync(string base64Image, string fileNamePrefix = "image") + { + try + { + if (string.IsNullOrWhiteSpace(base64Image)) + { + _logger.LogWarning("Base64图片数据为空"); + return null; + } + + // 解析Base64数据和MIME类型 + string base64Data; + string contentType = "image/png"; + string extension = ".png"; + + if (base64Image.Contains(',')) + { + // 格式: data:image/png;base64,xxxxx + var parts = base64Image.Split(','); + base64Data = parts[1]; + + // 解析MIME类型 + var header = parts[0]; // data:image/png;base64 + if (header.Contains(':') && header.Contains(';')) + { + var mimeType = header.Split(':')[1].Split(';')[0]; + contentType = mimeType; + extension = mimeType switch + { + "image/jpeg" => ".jpg", + "image/jpg" => ".jpg", + "image/png" => ".png", + "image/gif" => ".gif", + "image/webp" => ".webp", + _ => ".png" + }; + } + } + else + { + base64Data = base64Image; + } + + // 解码Base64数据 + byte[] imageBytes; + try + { + imageBytes = Convert.FromBase64String(base64Data); + } + catch (FormatException ex) + { + _logger.LogWarning(ex, "Base64解码失败"); + return null; + } + + // 验证文件大小 (10MB) + if (imageBytes.Length > 10 * 1024 * 1024) + { + _logger.LogWarning("Base64图片大小超过限制: {Size} bytes", imageBytes.Length); + return null; + } + + // 生成文件名 + var fileName = $"{fileNamePrefix}_{DateTime.UtcNow:yyyyMMddHHmmss}{extension}"; + + // 获取存储提供者并上传 + var provider = await GetStorageProviderAsync(); + using var stream = new MemoryStream(imageBytes); + var result = await provider.UploadAsync(stream, fileName, contentType); + + if (result.Success) + { + _logger.LogInformation("Base64图片上传成功: {Url}", result.Url); + return result.Url; + } + else + { + _logger.LogWarning("Base64图片上传失败: {Error}", result.ErrorMessage); + return null; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Base64图片上传异常"); + return null; + } + } + /// /// 验证文件 /// diff --git a/server/HoneyBox/src/HoneyBox.Api/Controllers/UserController.cs b/server/HoneyBox/src/HoneyBox.Api/Controllers/UserController.cs index 4fc90724..5d11fd65 100644 --- a/server/HoneyBox/src/HoneyBox.Api/Controllers/UserController.cs +++ b/server/HoneyBox/src/HoneyBox.Api/Controllers/UserController.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using HoneyBox.Admin.Business.Services.Interfaces; using HoneyBox.Core.Interfaces; using HoneyBox.Model.Base; using HoneyBox.Model.Models.Asset; @@ -24,6 +25,7 @@ public class UserController : ControllerBase private readonly IAssetService _assetService; private readonly IVipService _vipService; private readonly IQuanYiService _quanYiService; + private readonly IUploadService _uploadService; private readonly ILogger _logger; public UserController( @@ -32,6 +34,7 @@ public class UserController : ControllerBase IAssetService assetService, IVipService vipService, IQuanYiService quanYiService, + IUploadService uploadService, ILogger logger) { _userService = userService; @@ -39,6 +42,7 @@ public class UserController : ControllerBase _assetService = assetService; _vipService = vipService; _quanYiService = quanYiService; + _uploadService = uploadService; _logger = logger; } @@ -166,12 +170,17 @@ public class UserController : ControllerBase if (!string.IsNullOrWhiteSpace(request.Imagebase)) { // Base64图片上传到腾讯云COS - var headimgUrl = await UploadBase64ImageAsync(request.Imagebase, userId.Value); + var headimgUrl = await _uploadService.UploadBase64ImageAsync(request.Imagebase, $"avatar_{userId}"); if (!string.IsNullOrWhiteSpace(headimgUrl)) { updateDto.Headimg = headimgUrl; hasUpdate = true; } + else + { + _logger.LogWarning("头像上传失败: UserId={UserId}", userId); + return ApiResponse.Fail("头像上传失败,请重试"); + } } else if (!string.IsNullOrWhiteSpace(request.Headimg)) { @@ -524,51 +533,5 @@ public class UserController : ControllerBase return userId; } - /// - /// 上传Base64图片到腾讯云COS - /// - /// Base64编码的图片数据 - /// 用户ID - /// 上传后的图片URL - private async Task UploadBase64ImageAsync(string base64Image, int userId) - { - try - { - // 移除Base64前缀(如果有) - var base64Data = base64Image; - if (base64Image.Contains(",")) - { - base64Data = base64Image.Split(',')[1]; - } - - // 解码Base64数据 - var imageBytes = Convert.FromBase64String(base64Data); - - // TODO: 实现腾讯云COS上传 - // 目前返回一个占位URL,实际应该上传到COS并返回真实URL - // 可以在后续添加ICosUploadService接口和实现 - - // 临时方案:将图片保存到本地并返回相对路径 - var fileName = $"avatar_{userId}_{DateTime.UtcNow:yyyyMMddHHmmss}.png"; - var uploadPath = Path.Combine("wwwroot", "uploads", "avatars"); - - if (!Directory.Exists(uploadPath)) - { - Directory.CreateDirectory(uploadPath); - } - - var filePath = Path.Combine(uploadPath, fileName); - await System.IO.File.WriteAllBytesAsync(filePath, imageBytes); - - // 返回相对URL - return $"/uploads/avatars/{fileName}"; - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to upload base64 image for user: {UserId}", userId); - return null; - } - } - #endregion } diff --git a/server/HoneyBox/src/HoneyBox.Api/HoneyBox.Api.csproj b/server/HoneyBox/src/HoneyBox.Api/HoneyBox.Api.csproj index 157d3a9c..a885174e 100644 --- a/server/HoneyBox/src/HoneyBox.Api/HoneyBox.Api.csproj +++ b/server/HoneyBox/src/HoneyBox.Api/HoneyBox.Api.csproj @@ -28,6 +28,7 @@ +