网站首页 网站源码
using System.Security.Cryptography;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Public.ViewModel.V4;
using Dpz.Core.Service.ObjectStorage.Services;
using Dpz.Core.Service.V4.Services;
using Dpz.Core.Web.Models.EventRequest;
using SixLabors.ImageSharp;
namespace Dpz.Core.Web.EventHandlers;
public class PublishPhotoEventHandler(
IPictureRecordService pictureRecordService,
IObjectStorageOperation objectStorageService,
IConfiguration configuration,
ILogger<PublishPhotoEventHandler> logger
) : IRequestHandler<PublishPhotoRequest, IActionResult>
{
public async Task<IActionResult> Handle(
PublishPhotoRequest request,
CancellationToken cancellationToken
)
{
return string.IsNullOrWhiteSpace(request.Id)
? await CreatePhotoRecordAsync(request, cancellationToken)
: await UpdateInformationAsync(request, cancellationToken);
}
private static string? ValidateCreate(PublishPhotoRequest request)
{
if (request.Photo is not { Length: > 0 } || !request.Photo.ContentType.Contains("image"))
{
return "请选择照片";
}
if (request.Tags is not { Count: > 0 })
{
return "请选择标签";
}
return null;
}
private async Task<IActionResult> CreatePhotoRecordAsync(
PublishPhotoRequest request,
CancellationToken cancellationToken = default
)
{
var validateMessage = ValidateCreate(request);
if (!string.IsNullOrWhiteSpace(validateMessage))
{
return new JsonResult(new ResultInfo(validateMessage));
}
using var memoryStream = new MemoryStream();
await request.Photo!.CopyToAsync(memoryStream, cancellationToken);
var bytes = memoryStream.ToArray();
var path = new List<string> { "images", "album", DateTime.Now.ToString("yyyy-MM") };
if (
!string.Equals(
configuration["AgileConfig:env"],
"PROD",
StringComparison.OrdinalIgnoreCase
)
)
{
path.Insert(0, "test");
}
var filename = $"{ObjectId.GenerateNewId()}.{await GetImageFormatAsync(bytes)}";
var result = await objectStorageService.UploadAsync(
bytes,
path,
filename,
cancellationToken
);
var pictureRecord = new VmPictureRecord
{
Creator = request.Creator,
UploadTime = DateTime.Now,
Tags = request.Tags,
Description = request.Description,
Category = PictureCategory.Album,
AccessUrl = result.AccessUrl,
Length = bytes.Length,
ObjectStorageUploadTime = DateTime.Now,
Md5 = CalculateMd5(bytes),
Width = result.Width,
Height = result.Height,
};
var photo = await pictureRecordService.CreateRecordAsync(pictureRecord, cancellationToken);
return new JsonResult(new ResultInfo(photo));
}
private async Task<string?> ValidateUpdateInformationAsync(PublishPhotoRequest request)
{
var pictureRecord = await pictureRecordService.GetPictureRecordAsync(request.Id!);
if (pictureRecord == null)
{
return "该照片记录不存在";
}
if (pictureRecord.Creator.Id != request.Creator.Id)
{
return "没有权限修改该照片信息";
}
if (request.Tags is not { Count: > 0 })
{
return "请选择标签";
}
return null;
}
private async Task<IActionResult> UpdateInformationAsync(
PublishPhotoRequest request,
CancellationToken cancellationToken = default
)
{
var validateMessage = await ValidateUpdateInformationAsync(request);
if (!string.IsNullOrWhiteSpace(validateMessage))
{
return new JsonResult(new ResultInfo(validateMessage));
}
var recordChange = new VmPictureRecordChange
{
Category = PictureCategory.Album,
Description = request.Description,
Tags = request.Tags,
Id = request.Id,
};
var photo = await pictureRecordService.ChangeInformationAsync(
recordChange,
cancellationToken
);
return new JsonResult(new ResultInfo(photo));
}
private static string CalculateMd5(byte[] bytes)
{
var hash = MD5.HashData(bytes);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
private async Task<string> GetImageFormatAsync(byte[] bytes)
{
try
{
using var stream = new MemoryStream(bytes);
using var image = await Image.LoadAsync(stream);
return image.Metadata.DecodedImageFormat?.FileExtensions.FirstOrDefault() ?? "jpg";
}
catch (Exception e)
{
logger.LogError(e, "get image format fail");
return "jpg";
}
}
}
上述代码是一个 ASP.NET Core 的事件处理程序,主要用于处理照片发布请求。它实现了 IRequestHandler<PublishPhotoRequest, IActionResult>
接口,负责处理 PublishPhotoRequest
类型的请求,并返回一个 IActionResult
类型的响应。以下是代码的主要功能和结构的详细解释:
PublishPhotoEventHandler
类的构造函数接受多个依赖项,包括:
IPictureRecordService
:用于处理与照片记录相关的服务。IObjectStorageOperation
:用于处理对象存储操作的服务。IConfiguration
:用于访问应用程序的配置设置。ILogger<PublishPhotoEventHandler>
:用于记录日志。Handle
方法是处理请求的主要入口点。它根据请求中是否包含 Id
字段来决定是创建新的照片记录还是更新现有的照片信息:
Id
为空,调用 CreatePhotoRecordAsync
方法创建新的照片记录。Id
不为空,调用 UpdateInformationAsync
方法更新现有照片的信息。CreatePhotoRecordAsync
方法负责创建新的照片记录:
ValidateCreate
方法验证请求的有效性,确保上传的照片存在且是有效的图像文件,并且至少选择了一个标签。objectStorageService.UploadAsync
方法将照片上传到对象存储,并获取上传结果。VmPictureRecord
对象,填充照片的相关信息(如创建者、上传时间、标签、描述等)。pictureRecordService.CreateRecordAsync
方法将照片记录保存到数据库中,并返回结果。UpdateInformationAsync
方法负责更新现有照片的信息:
ValidateUpdateInformationAsync
方法验证请求的有效性,确保照片记录存在且请求者有权限修改该记录。VmPictureRecordChange
对象,填充要更新的信息。pictureRecordService.ChangeInformationAsync
方法更新照片记录,并返回结果。ValidateCreate
:验证创建请求的有效性,确保照片和标签都已提供。ValidateUpdateInformationAsync
:验证更新请求的有效性,确保照片记录存在且请求者有权限进行修改。CalculateMd5
:计算给定字节数组的 MD5 哈希值,用于唯一标识照片内容。GetImageFormatAsync
:根据字节数组获取图像格式,使用 ImageSharp
库加载图像并返回其文件扩展名。整体而言,这段代码实现了一个用于处理照片上传和信息更新的事件处理程序,确保请求的有效性,并与对象存储和数据库进行交互,以存储和管理照片记录。