using AngleSharp.Html.Parser;
using Dpz.Core.Infrastructure;
using Dpz.Core.MessageQueue.Abstractions;
using Dpz.Core.MessageQueue.Models;
using Dpz.Core.Public.ViewModel.Messages;
using Dpz.Core.Service.Mediator;
namespace Dpz.Core.Web.Jobs.MessageHandlers;
/// <summary>
/// 删除 Markdown 内容消息处理器
/// 解析 Markdown 中的图片并继续发布删除图片消息
/// </summary>
public class DeleteMarkdownHandler(
IMessagePublisher<RemoveImagesMessage> removeImagesPublisher,
ILogger<DeleteMarkdownHandler> logger
) : IMessageHandler<DeleteMarkdownMessage>
{
private readonly HtmlParser _htmlParser = new();
public async Task<MessageHandlerResult> HandleAsync(
DeleteMarkdownMessage message,
CancellationToken cancellationToken
)
{
try
{
if (message.MarkdownContents.Count == 0)
{
logger.LogInformation("没有需要处理的 Markdown 内容");
return MessageHandlerResult.Ok();
}
var allImages = new List<string>();
foreach (var markdown in message.MarkdownContents)
{
if (string.IsNullOrWhiteSpace(markdown))
{
continue;
}
var images = await ExtractImagesFromMarkdownAsync(markdown);
allImages.AddRange(images);
}
if (allImages.Count > 0)
{
// 批量发布删除图片队列消息
var messages = allImages.Select(x => new RemoveImagesMessage { ImageUrl = x });
await removeImagesPublisher.PublishBatchAsync(
messages,
cancellationToken: cancellationToken
);
logger.LogInformation(
"处理 DeleteMarkdown 完成,从 {MarkdownCount} 个 Markdown 中提取到 {ImageCount} 张图片并发布到队列",
message.MarkdownContents.Count,
allImages.Count
);
}
else
{
logger.LogInformation(
"处理 DeleteMarkdown 完成,从 {MarkdownCount} 个 Markdown 中未提取到图片",
message.MarkdownContents.Count
);
}
return MessageHandlerResult.Ok();
}
catch (Exception ex)
{
logger.LogError(ex, "处理 DeleteMarkdown 消息失败");
return MessageHandlerResult.Fail($"处理 DeleteMarkdown 消息失败: {ex.Message}");
}
}
/// <summary>
/// 从 Markdown 内容中提取图片 URL
/// </summary>
private async Task<List<string>> ExtractImagesFromMarkdownAsync(string markdown)
{
try
{
// 将 Markdown 转换为 HTML
var htmlContent = markdown.MarkdownToHtml();
// 解析 HTML
var document = await _htmlParser.ParseDocumentAsync(htmlContent);
var imageElements = document.GetElementsByTagName("img");
// 提取图片 URL
return imageElements.GetElementsImageUrls();
}
catch (Exception ex)
{
logger.LogError(ex, "从 Markdown 提取图片失败");
return [];
}
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
这是一个用于处理删除 Markdown 内容的消息处理器类。让我详细解释一下这段代码的功能和实现:
类的作用
DeleteMarkdownHandler 是一个消息处理器,专门用于处理 DeleteMarkdownMessage 类型的消息。当需要删除 Markdown 内容时,这个处理器会:
- 解析 Markdown 中包含的图片
- 发布删除图片的消息到消息队列
依赖注入
通过构造函数注入两个依赖:
IMessagePublisher<RemoveImagesMessage>: 用于发布删除图片的消息ILogger<DeleteMarkdownHandler>: 用于记录日志
核心处理流程 (HandleAsync 方法)
- 输入验证: 检查是否有 Markdown 内容需要处理
- 图片提取: 遍历所有 Markdown 内容,提取其中的图片 URL
- 批量发布: 将提取到的图片 URL 转换为
RemoveImagesMessage并批量发布到消息队列 - 日志记录: 记录处理结果
- 异常处理: 捕获并记录任何处理过程中的异常
图片提取逻辑 (ExtractImagesFromMarkdownAsync 方法)
- Markdown 转 HTML: 使用
MarkdownToHtml()扩展方法将 Markdown 转换为 HTML - HTML 解析: 使用 AngleSharp 的
HtmlParser解析 HTML 文档 - 图片元素查找: 查找所有
<img>标签 - URL 提取: 使用
GetElementsImageUrls()扩展方法提取图片 URL
设计优势
- 异步处理: 整个处理流程都是异步的,提高性能
- 批量操作: 使用
PublishBatchAsync批量发布消息,提高效率 - 容错性: 完善的异常处理和日志记录
- 职责分离: 将图片删除作为单独的消息处理,遵循单一职责原则
- 可观测性: 详细的日志记录便于监控和调试
使用场景
这个处理器通常用于内容管理系统中,当用户删除包含图片的 Markdown 文章时,需要同步清理相关的图片资源,避免产生孤立文件。
AI 正在分析代码…
评论加载中...