StarBlog Development Notes (18): Implementing Packaged Upload of Local Typora Articles
Preface September was too busy; I only published three articles. I originally started working on this feature in early September, but it kept getting delayed until the National Day holiday when I finally had time to finish it and write this post~ I previously published a few articles about Python, and some friends left comments asking if I had stopped updating .Net. Of course not! I can only say**「I want it ALL」**, so I immediately followed up with an Asp-Net-Core development notes post. Then I’ll casually set a Flag: finish the main part of the StarBlog series by the end of this year (i.e., API development + admin front
目录9 个章节
Preface
September was too busy; I only published three articles. I originally started working on this feature in early September, but it kept getting delayed until the National Day holiday when I finally had time to finish it and write this post~
I previously published a few articles about Python, and some friends left comments asking if I had stopped updating .Net. Of course not! I can only say**「I want it ALL」**, so I immediately followed up with an Asp-Net-Core Development Notes post.
Then I’ll casually set a Flag: finish the main part of the StarBlog series by the end of this year (i.e., API development + admin frontend development; currently only the blog frontend and backend are done). Let’s go~
OK, back to this article. Programmers all like writing articles in Markdown, but since markdown is a plain-text format, how to save the images inserted in it becomes a major headache. Some people choose image hosting, but it may not remain valid forever; others choose local storage, where images remain valid forever, but then how to share the article becomes another problem…
I chose the second option: local storage. I write articles with Typora, and images are saved in a directory with the same name as the Markdown file (markdown.assets), which gives a great writing experience. Then the sharing problem is left to StarBlog—the original purpose of this project was to publish local articles as a blog.
Previously there was only a batch import feature for articles; now what I need to do is separately implement a packaged import feature for a single article.
As there are more and more articles, putting the series table of contents at the front is starting to affect reading, so starting from this post I’ll put it at the very end~
Implementation Approach
Suppose I write a Markdown article with Typora, with the filename: StarBlog.md, and insert several images in it. Based on the configuration, Typora will automatically generate a directory (StarBlog.assets) to store these images.
To implement import, I need to package this markdown file together with this image directory into a zip archive and upload it. The backend extracts the zip archive to a temporary directory, reads the Markdown file, parses its contents, and performs the import.
Code Implementation
OK, let’s start writing code.
Meanwhile, all project code has been uploaded to GitHub. Stars/Forks from all of you are welcome!
- Blog backend + frontend project: https://github.com/Deali-Axy/StarBlog
- Admin dashboard frontend project: https://github.com/Deali-Axy/StarBlog-Admin
Unzipping
First is the unzipping feature. The .Net standard library comes with ZipFile for working with zip archives, in System.IO.Compression—just use it and you’re done.
Before extracting, you need to copy the file to a temporary directory first, and create a new temporary directory to hold the extracted files.
Add the following code in Services/BlogServices.cs
public async Task<Post> Upload(PostCreationDto dto, IFormFile file) {
// 先复制到临时文件
var tempFile = Path.GetTempFileName();
await using (var fs = new FileStream(tempFile, FileMode.Create)) {
await file.CopyToAsync(fs);
}
// 设定解压用的临时目录
var extractPath = Path.Combine(Path.GetTempPath(), "StarBlog", Guid.NewGuid().ToString());
// 使用 GBK 编码解压,防止中文文件名乱码
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
ZipFile.ExtractToDirectory(tempFile, extractPath, Encoding.GetEncoding("GBK"));
}
Originally, just calling ZipFile.ExtractToDirectory() would be enough to extract, but if files in the archive use Chinese names, you have to set the encoding first.
Parsing Markdown
As for parsing Markdown in C#, I already wrote about it at the start of this series, so I won’t be a broken record here. You can check out these two articles directly:
- Developing a Blog Project with .NetCore: StarBlog - (4) Batch Importing Markdown Blog Posts
- Parsing Markdown Documents in C# and Replacing Image Links
Here’s the code.
Since this is a single-article import, after getting all *.md files in the temporary directory I only take the first file to process (in theory there shouldn’t be more than one anyway~)
var dir = new DirectoryInfo(extractPath);
var files = dir.GetFiles("*.md");
var mdFile = files.First();
using var reader = mdFile.OpenText();
var content = await reader.ReadToEndAsync();
var post = new Post {
Id = GuidUtils.GuidTo16String(),
Status = "已发布",
Title = dto.Title ?? $"{DateTime.Now.ToLongDateString()} 文章",
IsPublish = true,
Content = content,
Path = "",
CreationTime = DateTime.Now,
LastUpdateTime = DateTime.Now,
CategoryId = dto.CategoryId,
};
var assetsPath = Path.Combine(_environment.WebRootPath, "media", "blog");
var processor = new PostProcessor(extractPath, assetsPath, post);
// 处理文章标题和状态
processor.InflateStatusTitle();
// 处理文章正文内容
// 导入文章的时候一并导入文章里的图片,并对图片相对路径做替换操作
post.Content = processor.MarkdownParse();
post.Summary = processor.GetSummary(200);
For Markdown-related processing, I encapsulated a PostProcessor object, in StarBlog.Share.
Handling Multi-level Categories
If the article’s category is not a first-level category, find all the categories above it and line them up one by one, to make later processing easier.
// 处理多级分类
var category = await _categoryRepo.Where(a => a.Id == dto.CategoryId).FirstAsync();
if (category == null) {
post.Categories = "0";
}
else {
var categories = new List<Category> {category};
var parent = category.Parent;
while (parent != null) {
categories.Add(parent);
parent = parent.Parent;
}
categories.Reverse();
post.Categories = string.Join(",", categories.Select(a => a.Id));
}
Finally, Save
Done~
// 存入数据库
post = await _postRepo.InsertAsync(post);
Series Articles
- Developing a Blog Project with .NetCore: StarBlog - (1) Why Do You Need to Write Your Own Blog?
- Developing a Blog Project with .NetCore: StarBlog - (2) Environment Setup and Creating the Project
- Developing a Blog Project with .NetCore: StarBlog - (3) Model Design
- Developing a Blog Project with .NetCore: StarBlog - (4) Batch Importing Markdown Blog Posts
- Developing a Blog Project with .NetCore: StarBlog - (5) Starting to Build the Web Project
- Developing a Blog Project with .NetCore: StarBlog - (6) Page Development: Blog Post List
- Developing a Blog Project with .NetCore: StarBlog - (7) Page Development: Post Detail Page
- Developing a Blog Project with .NetCore: StarBlog - (8) Displaying the Category Hierarchy
- Developing a Blog Project with .NetCore: StarBlog - (9) Batch Importing Images
- Developing a Blog Project with .NetCore: StarBlog - (10) Image Waterfall Layout
- Developing a Blog Project with .NetCore: StarBlog - (11) Implementing Visit Statistics
- Developing a Blog Project with .NetCore: StarBlog - (12) Dynamic Compilation of Razor Pages
- Developing a Blog Project with .NetCore: StarBlog - (13) Adding Friend Links
- Developing a Blog Project with .NetCore: StarBlog - (14) Implementing Theme Switching
- Developing a Blog Project with .NetCore: StarBlog - (15) Generating Random-Size Images
- Developing a Blog Project with .NetCore: StarBlog - (16) Some New Features (Monitoring/Statistics/Configuration/Initialization)
- Developing a Blog Project with .NetCore: StarBlog - (17) Automatically Downloading External Images in Posts
- Developing a Blog Project with .NetCore: StarBlog - (18) Implementing Packaged Upload of Local Typora Articles
References
_EOF_
StarBlog Development Notes (18): Implementing Packaged Upload of Local Typora Articles
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
基于.NetCore开发博客项目 StarBlog - (30) 实现评论系统
开发者终于更新评论系统,代码量庞大只贴关键逻辑,GitHub自便。前端ElementUI与Bootstrap风格冲突,却称和谐?评论需邮箱验证码,审核流程繁琐,自动不通过还得人工。
2025-04-27 · StarBlog博客开发笔记 · 约 1 分钟
StarBlog博客开发笔记(7):页面开发之文章详情页面
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetCore开发博客项目 StarBlog - (3) 模型设计 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入 基于.NetCore开发博客项目 StarBl
2022-05-20 · StarBlog博客开发笔记 · 约 1 分钟
StarBlog博客开发笔记(4):markdown博客批量导入
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetCore开发博客项目 StarBlog - (3) 模型设计 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入 ... 前言 上周介绍了博客的模型设计,现在模
2025-04-27 · StarBlog博客开发笔记 · 约 1 分钟
StarBlog博客开发笔记(10):图片展示-瀑布流-首页卡片
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetCore开发博客项目 StarBlog - (3) 模型设计 基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入 基于.NetCore开发博客项目 StarBl
2022-11-22 · StarBlog博客开发笔记 · 约 1 分钟
讨论
共 0 条加载评论中…