Files
glz bdaa6a0dc8 refactor: 统一业务异常处理,标准化结果码和错误响应
1.  新增并完善ResultCode枚举,补充标准HTTP状态码对应的业务状态码
2.  重构BusinessException,新增基于ResultCode的构造函数和ThrowIf扩展方法
3.  替换所有硬编码的HTTP状态码为统一的ResultCode枚举
4.  优化全局异常中间件,根据业务状态码映射对应HTTP状态码并规范化JSON响应
5.  修复OssImageHelper和AutoDotCodeConsumer中的OSS文件处理逻辑
6.  新增用户答题快照实体类
7.  清理废弃的宠物模块迁移脚本
2026-06-29 16:34:26 +08:00

112 lines
4.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.Extensions.Logging;
using QYZH.InteractiveMagazine.Common.Extensions;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
namespace QYZH.InteractiveMagazine.Infrastructure.OSS;
/// <summary>
/// OSS 图片搬运辅助类
/// 负责将 temp 临时目录下的文件搬运到正式目录
/// </summary>
public class OssImageHelper
{
private readonly OssService _ossService;
private readonly ILogger _logger;
public OssImageHelper(OssService ossService, ILogger logger)
{
_ossService = ossService;
_logger = logger;
}
/// <summary>
/// 判断图片是否在 temp 临时目录
/// </summary>
public static bool IsTempImage(string? imageUrl)
{
if (string.IsNullOrWhiteSpace(imageUrl)) return false;
return imageUrl.Contains("/temp/", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// 将 temp 目录下的图片搬运到正式目录,返回正式路径
/// 如果图片不在 temp 目录,原样返回
/// </summary>
/// <param name="imageUrl">原始图片 URL可能是完整 URL 或相对路径)</param>
/// <param name="formalFolder">正式目录前缀,如 "product/makeupcard/123" 或 "pet/skin/456"</param>
/// <returns>正式路径(相对路径),搬运失败时抛出异常</returns>
public async Task<string> MoveToFormalAsync(string imageUrl, string formalFolder)
{
if (!IsTempImage(imageUrl))
return imageUrl;
// 提取 OSS 相对路径(去掉域名前缀)
var sourcePath = imageUrl.RemoveDomain();
if (string.IsNullOrWhiteSpace(sourcePath))
{
_logger.LogWarning("图片路径解析失败ImageUrl: {ImageUrl}", imageUrl);
return imageUrl;
}
// URL 解码(处理中文文件名)
sourcePath = Uri.UnescapeDataString(sourcePath);
// 提取文件名
var fileName = Path.GetFileName(sourcePath);
if (string.IsNullOrWhiteSpace(fileName))
{
_logger.LogWarning("无法从路径中提取文件名Path: {Path}", sourcePath);
return imageUrl;
}
// 生成正式路径
var targetPath = $"{formalFolder}/{fileName}";
_logger.LogInformation("开始搬运图片Source: {Source} -> Target: {Target}", sourcePath, targetPath);
try
{
// 拷贝文件到正式目录
var copyResult = _ossService.CopyObject(sourcePath, targetPath);
if (!copyResult)
{
_logger.LogError("OSS 图片拷贝失败Source: {Source}, Target: {Target}", sourcePath, targetPath);
throw new Exception("OSS 图片拷贝失败");
}
// 删除临时文件(失败不影响主流程)
var deleteResult = _ossService.DeleteObject(sourcePath);
if (!deleteResult)
{
_logger.LogWarning("OSS 临时文件删除失败不影响主流程Source: {Source}", sourcePath);
}
_logger.LogInformation("图片搬运成功Target: {Target}", targetPath);
return targetPath;
}
catch (Exception ex) when (ex is not BusinessException)
{
_logger.LogError(ex, "OSS 图片搬运异常Source: {Source}, Target: {Target}", sourcePath, targetPath);
throw new BusinessException("图片搬运失败,请重试", ResultCode.GLOBAL_ERROR);
}
}
/// <summary>
/// 批量搬运 temp 图片到正式目录
/// </summary>
/// <param name="imageUrls">原始图片 URL 列表</param>
/// <param name="formalFolder">正式目录前缀</param>
/// <returns>正式路径列表(顺序与输入一致)</returns>
public async Task<List<string>> MoveBatchToFormalAsync(IEnumerable<string> imageUrls, string formalFolder)
{
var results = new List<string>();
foreach (var url in imageUrls)
{
var formal = await MoveToFormalAsync(url, formalFolder);
results.Add(formal);
}
return results;
}
}