Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Infrastructure/OSS/OssImageHelper.cs
glz 296d87b245 feat: 新增宠物进化分组接口、OSS图片搬运功能及配置更新
1. 新增皮肤按进化阶段分组的输出DTO
2. 新增宠物相关便捷查询接口并实现对应控制器
3. 新增OSS图片搬运辅助类,实现临时文件迁移逻辑
4. 为商品、宠物相关服务添加OSS图片自动迁移功能
5. 调整微信授权同步逻辑移除异步等待
6. 更新配置文件中的微信密钥和OSS存储信息
7. 注册SDK服务到DI容器
2026-06-09 18:02:26 +08:00

111 lines
4.0 KiB
C#
Raw 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;
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("图片搬运失败,请重试", 500);
}
}
/// <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;
}
}