如何使用.NetCore批量导入Markdown博客到StarBlog项目?

2026-05-06 03:562阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1685个文字,预计阅读时间需要7分钟。

如何使用.NetCore批量导入Markdown博客到StarBlog项目?

系列文章:基于.NetCore开发博客项目StarBlog-(1) 为什么需要自己写一个博客?系列文章:基于.NetCore开发博客项目StarBlog-(2) 环境准备和创建项目系列文章:基于.NetCore开发博客项目StarBlog-(3) 模型设计

系列文章
  • 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?
  • 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目
  • 基于.NetCore开发博客项目 StarBlog - (3) 模型设计
  • 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入
  • ...
前言

上周介绍了博客的模型设计,现在模型设计好了,要开始导入数据了。

我们要把一个文件夹内的所有markdown文件导入,目录结构作为文章的分类,文件名作为文章的标题,同时把文件的创建、更新日期作为文章的发表时间。

大概的思路就是先用.Net的标准库遍历目录,用第三方的markdown解析库处理文章内容,然后通过ORM写入数据库。

PS:明天就是五一劳动节了,祝各位无产阶级劳动者节日快乐~

相关技术
  • 文件IO相关API
  • 正则表达式
  • ORM:FreeSQL
  • markdown解析库:Markdig
开始写代码

我们首先从最关键的markdown内容解析、图片提取、标题处理说起。

为了处理markdown内容,我搜了一下相关资料,发现.Net Core目前能用的只有Markdig这个库,由于还处在开发阶段,没有完整文档,只能边看github主页的一点点说明边自己结合例子来用。没办法,没别的好的选择,又懒得(菜)造轮子,只能将就了。

Markdig官网地址:github.com/xoofx/markdig

如何使用.NetCore批量导入Markdown博客到StarBlog项目?

StarBlog.Migrate项目里新建一个Class:PostProcessor,我们要在这个class里实现markdown文件相关的处理逻辑。

PostProcessor.cs的完整代码在这:github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Migrate/PostProcessor.cs

构造方法:

private readonly Post _post; private readonly string _importPath; private readonly string _assetsPath; public PostProcessor(string importPath, string assetsPath, Post post) { _post = post; _assetsPath = assetsPath; _importPath = importPath; }

其中

  • Post:我们上一篇里设计的文章模型
  • importPath:要导入的markdown文件夹路径
  • assetsPath:资源文件存放路径,用于存放markdown里的图片,本项目设置的路径是StarBlog.Web/wwwroot/media/blog
文章摘要提取

文章摘要提取,我做了简单的处理,把markdown内容渲染成文本,然后截取前n个字形成摘要,代码如下:

public string GetSummary(int length) { return _post.Content == null ? string.Empty : Markdown.ToPlainText(_post.Content).Limit(length); } 文章状态和标题处理

之前在用本地markdown文件写博客的时候,出于个人习惯,我会在文件名里加上代表状态的前缀,例如未完成的文章是这样的:

(未完成)StarBlog博客开发笔记(4):markdown博客批量导入

或者已完成但未发布,会加上(未发布)

等到发布之后,就把前缀去掉,所以在导入的时候,我要用正则表达式对这个前缀进行提取,让导入数据库的博客文章标题不要再带上前缀了。

代码如下

public (string, string) InflateStatusTitle() { const string pattern = @"^((.+))(.+)$"; var status = _post.Status ?? "已发布"; var title = _post.Title; if (string.IsNullOrEmpty(title)) return (status, $"未命名文章{_post.CreationTime.ToLongDateString()}"); var result = Regex.Match(title, pattern); if (!result.Success) return (status, title); status = result.Groups[1].Value; title = result.Groups[2].Value; _post.Status = status; _post.Title = title; if (!new[] { "已发表", "已发布" }.Contains(_post.Status)) { _post.IsPublish = false; } return (status, title); }

逻辑很简单,判断标题是否为空(对文件名来说这不太可能,不过为了严谨一点还是做了),然后用正则匹配,匹配到了就把状态提取出来,没匹配到就默认"已发布"

图片提取 & 替换

markdown内容处理比较复杂的就是这部分了,所以我之前就把这部分单独拿出来写了一篇文章来介绍,所以本文就不再重复太多,详情可以看我前面的这篇文章:C#解析Markdown文档,实现替换图片链接操作

然后回到我们的博客项目,这部分的代码如下

public string MarkdownParse() { if (_post.Content == null) { return string.Empty; } var document = Markdown.Parse(_post.Content); foreach (var node in document.AsEnumerable()) { if (node is not ParagraphBlock { Inline: { } } paragraphBlock) continue; foreach (var inline in paragraphBlock.Inline) { if (inline is not LinkInline { IsImage: true } linkInline) continue; if (linkInline.Url == null) continue; if (linkInline.Url.StartsWith("docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/file-system/how-to-iterate-through-a-directory-tree

关键代码如下,完整代码在这:github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Migrate/Program.cs

void WalkDirectoryTree(DirectoryInfo root) { Console.WriteLine($"正在扫描文件夹:{root.FullName}"); FileInfo[]? files = null; DirectoryInfo[]? subDirs = null; try { files = root.GetFiles("*.md"); } catch (UnauthorizedAccessException e) { Console.WriteLine(e.Message); } catch (DirectoryNotFoundException e) { Console.WriteLine(e.Message); } if (files != null) { foreach (var fi in files) { Console.WriteLine(fi.FullName); // 处理文章的代码,省略 } } subDirs = root.GetDirectories(); foreach (var dirInfo in subDirs) { if (exclusionDirs.Contains(dirInfo.Name)) { continue; } if (dirInfo.Name.EndsWith(".assets")) { continue; } WalkDirectoryTree(dirInfo); } }

用的这个方法叫做“前序遍历”,即先处理目录下的文件,然后再处理目录下的子目录。

递归的方法写起来比较简单,但是有一个缺陷是如果目录结构嵌套太多的话,可能会堆栈溢出,可以考虑换用基于Stack<T>模式的遍历,不过作为博客的目录层级结构应该不会太多,所以我只用简单的~

写入数据库

本项目用到的ORM是FreeSQL,ORM操作在后续的网站开发中会有比较多的介绍,因此本文略过,文章数据写入数据库的代码很简单,可以直接看:github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Migrate/Program.cs

结束

OK,博客批量导入就介绍了这么多,几个麻烦的地方处理好之后也没啥难度了,有了文章数据之后,才能方便接下来开始开发博客网站~

大概就这些了,下篇文章见~

同时所有项目代码已经上传GitHub,欢迎各位大佬Star/Fork!

  • 博客后端+前台项目地址:github.com/Deali-Axy/StarBlog
  • 管理后台前端项目地址:github.com/Deali-Axy/StarBlog-Admin
微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。

本文共计1685个文字,预计阅读时间需要7分钟。

如何使用.NetCore批量导入Markdown博客到StarBlog项目?

系列文章:基于.NetCore开发博客项目StarBlog-(1) 为什么需要自己写一个博客?系列文章:基于.NetCore开发博客项目StarBlog-(2) 环境准备和创建项目系列文章:基于.NetCore开发博客项目StarBlog-(3) 模型设计

系列文章
  • 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客?
  • 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目
  • 基于.NetCore开发博客项目 StarBlog - (3) 模型设计
  • 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入
  • ...
前言

上周介绍了博客的模型设计,现在模型设计好了,要开始导入数据了。

我们要把一个文件夹内的所有markdown文件导入,目录结构作为文章的分类,文件名作为文章的标题,同时把文件的创建、更新日期作为文章的发表时间。

大概的思路就是先用.Net的标准库遍历目录,用第三方的markdown解析库处理文章内容,然后通过ORM写入数据库。

PS:明天就是五一劳动节了,祝各位无产阶级劳动者节日快乐~

相关技术
  • 文件IO相关API
  • 正则表达式
  • ORM:FreeSQL
  • markdown解析库:Markdig
开始写代码

我们首先从最关键的markdown内容解析、图片提取、标题处理说起。

为了处理markdown内容,我搜了一下相关资料,发现.Net Core目前能用的只有Markdig这个库,由于还处在开发阶段,没有完整文档,只能边看github主页的一点点说明边自己结合例子来用。没办法,没别的好的选择,又懒得(菜)造轮子,只能将就了。

Markdig官网地址:github.com/xoofx/markdig

如何使用.NetCore批量导入Markdown博客到StarBlog项目?

StarBlog.Migrate项目里新建一个Class:PostProcessor,我们要在这个class里实现markdown文件相关的处理逻辑。

PostProcessor.cs的完整代码在这:github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Migrate/PostProcessor.cs

构造方法:

private readonly Post _post; private readonly string _importPath; private readonly string _assetsPath; public PostProcessor(string importPath, string assetsPath, Post post) { _post = post; _assetsPath = assetsPath; _importPath = importPath; }

其中

  • Post:我们上一篇里设计的文章模型
  • importPath:要导入的markdown文件夹路径
  • assetsPath:资源文件存放路径,用于存放markdown里的图片,本项目设置的路径是StarBlog.Web/wwwroot/media/blog
文章摘要提取

文章摘要提取,我做了简单的处理,把markdown内容渲染成文本,然后截取前n个字形成摘要,代码如下:

public string GetSummary(int length) { return _post.Content == null ? string.Empty : Markdown.ToPlainText(_post.Content).Limit(length); } 文章状态和标题处理

之前在用本地markdown文件写博客的时候,出于个人习惯,我会在文件名里加上代表状态的前缀,例如未完成的文章是这样的:

(未完成)StarBlog博客开发笔记(4):markdown博客批量导入

或者已完成但未发布,会加上(未发布)

等到发布之后,就把前缀去掉,所以在导入的时候,我要用正则表达式对这个前缀进行提取,让导入数据库的博客文章标题不要再带上前缀了。

代码如下

public (string, string) InflateStatusTitle() { const string pattern = @"^((.+))(.+)$"; var status = _post.Status ?? "已发布"; var title = _post.Title; if (string.IsNullOrEmpty(title)) return (status, $"未命名文章{_post.CreationTime.ToLongDateString()}"); var result = Regex.Match(title, pattern); if (!result.Success) return (status, title); status = result.Groups[1].Value; title = result.Groups[2].Value; _post.Status = status; _post.Title = title; if (!new[] { "已发表", "已发布" }.Contains(_post.Status)) { _post.IsPublish = false; } return (status, title); }

逻辑很简单,判断标题是否为空(对文件名来说这不太可能,不过为了严谨一点还是做了),然后用正则匹配,匹配到了就把状态提取出来,没匹配到就默认"已发布"

图片提取 & 替换

markdown内容处理比较复杂的就是这部分了,所以我之前就把这部分单独拿出来写了一篇文章来介绍,所以本文就不再重复太多,详情可以看我前面的这篇文章:C#解析Markdown文档,实现替换图片链接操作

然后回到我们的博客项目,这部分的代码如下

public string MarkdownParse() { if (_post.Content == null) { return string.Empty; } var document = Markdown.Parse(_post.Content); foreach (var node in document.AsEnumerable()) { if (node is not ParagraphBlock { Inline: { } } paragraphBlock) continue; foreach (var inline in paragraphBlock.Inline) { if (inline is not LinkInline { IsImage: true } linkInline) continue; if (linkInline.Url == null) continue; if (linkInline.Url.StartsWith("docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/file-system/how-to-iterate-through-a-directory-tree

关键代码如下,完整代码在这:github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Migrate/Program.cs

void WalkDirectoryTree(DirectoryInfo root) { Console.WriteLine($"正在扫描文件夹:{root.FullName}"); FileInfo[]? files = null; DirectoryInfo[]? subDirs = null; try { files = root.GetFiles("*.md"); } catch (UnauthorizedAccessException e) { Console.WriteLine(e.Message); } catch (DirectoryNotFoundException e) { Console.WriteLine(e.Message); } if (files != null) { foreach (var fi in files) { Console.WriteLine(fi.FullName); // 处理文章的代码,省略 } } subDirs = root.GetDirectories(); foreach (var dirInfo in subDirs) { if (exclusionDirs.Contains(dirInfo.Name)) { continue; } if (dirInfo.Name.EndsWith(".assets")) { continue; } WalkDirectoryTree(dirInfo); } }

用的这个方法叫做“前序遍历”,即先处理目录下的文件,然后再处理目录下的子目录。

递归的方法写起来比较简单,但是有一个缺陷是如果目录结构嵌套太多的话,可能会堆栈溢出,可以考虑换用基于Stack<T>模式的遍历,不过作为博客的目录层级结构应该不会太多,所以我只用简单的~

写入数据库

本项目用到的ORM是FreeSQL,ORM操作在后续的网站开发中会有比较多的介绍,因此本文略过,文章数据写入数据库的代码很简单,可以直接看:github.com/Deali-Axy/StarBlog/blob/master/StarBlog.Migrate/Program.cs

结束

OK,博客批量导入就介绍了这么多,几个麻烦的地方处理好之后也没啥难度了,有了文章数据之后,才能方便接下来开始开发博客网站~

大概就这些了,下篇文章见~

同时所有项目代码已经上传GitHub,欢迎各位大佬Star/Fork!

  • 博客后端+前台项目地址:github.com/Deali-Axy/StarBlog
  • 管理后台前端项目地址:github.com/Deali-Axy/StarBlog-Admin
微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。