add: 图片处理器

This commit is contained in:
jackfiled 2024-01-25 17:33:46 +08:00
parent 154ea2b7f2
commit ce066150cf
4 changed files with 101 additions and 1 deletions

View File

@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using YaeBlog.Core.Builder; using YaeBlog.Core.Builder;
using YaeBlog.Core.Models; using YaeBlog.Core.Models;
using YaeBlog.Core.Processors;
using YaeBlog.Core.Services; using YaeBlog.Core.Services;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NamingConventions;
@ -35,6 +36,10 @@ public static class BlogApplicationBuilderExtension
builder.Services.AddSingleton<RendererService>(); builder.Services.AddSingleton<RendererService>();
builder.Services.AddSingleton<EssayContentService>(); builder.Services.AddSingleton<EssayContentService>();
// 设置图像处理器
builder.Services.AddSingleton<ImagePostRenderProcessor>();
ImagePostRenderProcessor.AddImageApiEndpoint(builder);
builder.Services.AddHostedService<WebApplicationHostedService>((provider) builder.Services.AddHostedService<WebApplicationHostedService>((provider)
=> new WebApplicationHostedService(builder.WebApplicationBuilderConfigurations, => new WebApplicationHostedService(builder.WebApplicationBuilderConfigurations,
builder.WebApplicationConfigurations, provider)); builder.WebApplicationConfigurations, provider));

View File

@ -10,7 +10,7 @@ public static class BlogApplicationExtension
{ {
internal static void ConfigureDefaultBlogApplication(this BlogApplication application) internal static void ConfigureDefaultBlogApplication(this BlogApplication application)
{ {
//application.UsePostRenderProcessor<ImagePostRenderProcessor>(); application.UsePostRenderProcessor<ImagePostRenderProcessor>();
} }
public static void UsePreRenderProcessor<T>(this BlogApplication application) public static void UsePreRenderProcessor<T>(this BlogApplication application)

View File

@ -0,0 +1,94 @@
using AngleSharp;
using AngleSharp.Dom;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using YaeBlog.Core.Abstractions;
using YaeBlog.Core.Builder;
using YaeBlog.Core.Extensions;
using YaeBlog.Core.Models;
namespace YaeBlog.Core.Processors;
public class ImagePostRenderProcessor(ILogger<ImagePostRenderProcessor> logger,
IOptions<BlogOptions> options)
: IPostRenderProcessor
{
private static readonly IConfiguration s_configuration = Configuration.Default;
private readonly BlogOptions _options = options.Value;
public async Task<BlogEssay> ProcessAsync(BlogEssay essay)
{
BrowsingContext context = new(s_configuration);
IDocument html = await context.OpenAsync(
req => req.Content(essay.HtmlContent));
IEnumerable<IElement> imageElements = from node in html.All
where node.LocalName == "img"
select node;
foreach (IElement element in imageElements)
{
IAttr? attr = element.Attributes.GetNamedItem("src");
if (attr is not null)
{
logger.LogDebug("Found image link: '{}'", attr.Value);
attr.Value = GenerateImageLink(attr.Value, essay.FileName);
}
element.ClassList.Add("essay-image");
}
return essay.WithNewHtmlContent(html.DocumentElement.OuterHtml);
}
public string Name => "ImagePostRenderProcessor";
public static void AddImageApiEndpoint(BlogApplicationBuilder builder)
{
builder.ConfigureWebApplication((application) =>
{
application.MapGet("/api/files/{*filename}", ImageHandler);
});
}
private static Results<FileStreamHttpResult, NotFound> ImageHandler(string filename)
{
string contentType = "image/png";
if (filename.EndsWith("jpg") || filename.EndsWith("jpeg"))
{
contentType = "image/jpeg";
}
if (!Path.Exists(filename))
{
return TypedResults.NotFound();
}
Stream imageStream = File.OpenRead(filename);
return TypedResults.Stream(imageStream, contentType);
}
private string GenerateImageLink(string filename, string essayFilename)
{
if (!filename.Contains(essayFilename))
{
filename = Path.Combine(essayFilename, filename);
}
filename = Path.Combine(_options.Root, filename);
if (!Path.Exists(filename))
{
logger.LogWarning("Failed to found image: {}.", filename);
return _options.BannerImage;
}
string imageLink = "api/files/" + filename;
logger.LogDebug("Generate image link '{}' for image file '{}'.",
imageLink, filename);
return imageLink;
}
}

View File

@ -16,6 +16,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AngleSharp" Version="1.1.0" />
<PackageReference Include="Markdig" Version="0.34.0" /> <PackageReference Include="Markdig" Version="0.34.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />