Markdown转换器中间件

Markdown是一种非常流行的富文本格式,特别是在技术人员中应用广泛,Markdown文件的扩展名是.md。

由于Markdown并不是Web的标准,因此目前大部分浏览器并不支持直接显示Markdown文件。

在这里我们将编写一个在服务器端把Markdown转换为HTML的中间件。

我们开发的中间件是构建在ASP.NET Core内置的StaticFiles中间件之上的,并且在它之前运行。

所有的*.md文件都被放到wwwroot文件夹下,当我们请求wwwroot下其他的静态文件的时候,StaticFiles中间件会把它们返回给浏览器。

而当我们请求wwwroot下的*.md的时候,我们编写的中间件会读取对应的*.md文件并且把它们转换为HTML格式返回给浏览器。

*.md文件是文本文件,存在不同编码格式的问题,因此我们调用Ude.NetStandard这个NuGet包中的CharsetDetector类来探测流的编码,并且从流中读取文本,如以下代码:

C#
    /// <summary>
    /// 探测流的编码
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    private static string DetectCharset(Stream stream)
    {

        CharsetDetector detector = new();

        detector.Feed(stream);

        detector.DataEnd();

        string charset = detector.Charset ?? "UTF-8";

        stream.Position = 0;

        return charset;

    }
   

    /// <summary>
    /// 从流中读取文本
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    private static async Task<string> ReadTextAsync(Stream stream)
    {

        string charset = DetectCharset(stream);

        using var reader = new StreamReader(stream,Encoding.GetEncoding(charset));


        return await reader.ReadToEndAsync();

    }

}

DetectCharset方法用来探测流的编码,ReadText方法则调用DetectCharset探测流的编码,然后使用这个编码读取文本内容。

接下来,我们创建一个中间件读取*.md文件并且将其转换为HTML格式,如下面代码:

C#
    public class MarkDownViewerMiddleware(RequestDelegate _next, IWebHostEnvironment _environment, IMemoryCache _cache)
    {

        public async Task InvokeAsync(HttpContext context)
        {

            string path = context.Request.Path.Value ?? string.Empty;

            if (!path.EndsWith(".md"))
            {
                await _next(context);

                return;
            }

            //获取静态文件夹下的指定文件
            var file = _environment.WebRootFileProvider.GetFileInfo(path);

            if (!file.Exists)
            {
                await _next(context);

                return;
            }

            context.Response.ContentType = $"text/html;charset=UTF-8";

            context.Response.StatusCode = 200;

            //为了实现文件修改后用户能够立即获得最新文件,把文件的修改时间作为缓存键的一部分
            string cacheKey = nameof(MarkDownViewerMiddleware) + path + file.LastModified;

            //为了避免每次用户请求都读取和分析*.md文件,启用内存缓存来保存转换后的HTML内容
            var html = await _cache.GetOrCreateAsync(cacheKey, async ce =>
            {

                ce.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1);

                using var stearm = file.CreateReadStream();

                string text = await ReadContext.ReadTextAsync(stearm);

                //MarkdownSharp 转换为HTML
                Markdown markdown = new();

                return markdown.Transform(text);

            });

            await context.Response.WriteAsync(html);

        }

    }

编写完成中间件代码后,我们在wwwroot文件夹下放置若干个*.md文件,然后在Progarm.cs中注册这个中间件,如如下代码:

C#
app.UseMiddleware<MarkDownViewerMiddleware>();
app.UseStaticFiles();

MarkDownViewerMiddleware一定要放到StaticFiles之前。完成上面的代码后,运行项目,并且访问MD文件,我们就可以看到MD文件被转换为HTML格式,如图所示:

订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
滚动至顶部