1前言
九月太忙,只更新了三篇文章,本來這個功能是從九月初就開始做的,結果一直拖到現在國慶假期才有時間完善并且寫文章~
之前我更新了幾篇關于 Python 的文章,有朋友留言問是不是不更新 .Net 了,那肯定不能啊,我只能說「我 全 都 要」,所以我反手就更新了一篇Asp-Net-Core開發筆記。
然后順便立個Flag:今年底前完成StarBlog系列文章的主體部分(即API開發+后臺前端開發,目前只完成博客前后端部分),加油吧~
OK,說回本文,程序員都喜歡用Markdown來寫文章,但由于markdown是純文本格式,在其中插入的圖片要如何保存,就成了一大煩惱,有人選擇圖床,但不一定永久有效;有人選擇本地存儲,圖片永久有效,但如何分享文章又成了一個難題…
我選的就是第二種,本地存儲。使用Typora寫文章,圖片保存在和Markdown文件同名的目錄(markdown.assets)下,這樣可以獲得很好的寫作體驗,然后分享的問題就交給StarBlog吧,這個項目開發的初衷就是為了把本地的文章發表成博客。
不過之前只有批量導入文章的功能,現在我要做的就是單獨實現一個單篇文章打包導入的功能。
隨著文章越來越多,系列文章的目錄放前面有點影響閱讀了,所以從這篇開始我把它放到最后面~
2實現思路
假設我用Typora寫了一篇Markdown文章,文件名為:StarBlog.md
,并且在里面插入了若干圖片,根據配置,Typora會自動生成一個目錄(StarBlog.assets
)來存放這些圖片。
為了實現導入,我要把這個markdown文件和這個存圖片的目錄一起打包成zip壓縮文件上傳,后端將zip壓縮包解壓到臨時目錄,讀取Markdown文件,解析其中的內容,進行導入操作。
3代碼實現
OK,開始寫代碼吧
同時所有項目代碼已經上傳GitHub,歡迎各位大佬Star/Fork!
博客后端+前臺項目地址:https://github.com/Deali-Axy/StarBlog
管理后臺前端項目地址:https://github.com/Deali-Axy/StarBlog-Admin
解壓縮
首先是解壓縮功能,.Net標準庫自帶 ZipFile
這個庫用于操作zip壓縮包,在 System.IO.Compression
里,直接用就完事了。
解壓前得先把文件復制到臨時目錄,并創建一個新的臨時目錄來放解壓后的文件。
在 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"));
}
本來直接 ZipFile.ExtractToDirectory()
就能解壓了,但如果壓縮包里的文件用了中文名,就得先設置編碼。
解析Markdown
關于 C# 解析 Markdown ,在本系列一開始就寫過,所以這里就不再當復讀機了,可以直接看這兩篇文章:
基于.NetCore開發博客項目 StarBlog - (4) markdown博客批量導入
C#解析Markdown文檔,實現替換圖片鏈接操作
直接上代碼了
因為是做單篇文章導入,所以我這里獲取臨時目錄寫的所有 *.md
文件之后只取第一個文件來處理(理論上也不應該有多個~)
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);
Markdown相關的處理,我封裝了 PostProcessor
這個對象,在 StarBlog.Share
里。
處理多級分類
如果文章的分類不是一級分類,那么把它上面的所有分類找出來,一個個排好隊,方便后面處理。
//?處理多級分類
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));
}
最后保存
搞定~
//?存入數據庫
post?=?await?_postRepo.InsertAsync(post);
4系列文章
基于.NetCore開發博客項目 StarBlog - (1) 為什么需要自己寫一個博客?
基于.NetCore開發博客項目 StarBlog - (2) 環境準備和創建項目
基于.NetCore開發博客項目 StarBlog - (3) 模型設計
基于.NetCore開發博客項目 StarBlog - (4) markdown博客批量導入
基于.NetCore開發博客項目 StarBlog - (5) 開始搭建Web項目
基于.NetCore開發博客項目 StarBlog - (6) 頁面開發之博客文章列表
基于.NetCore開發博客項目 StarBlog - (7) 頁面開發之文章詳情頁面
基于.NetCore開發博客項目 StarBlog - (8) 分類層級結構展示
基于.NetCore開發博客項目 StarBlog - (9) 圖片批量導入
基于.NetCore開發博客項目 StarBlog - (10) 圖片瀑布流
基于.NetCore開發博客項目 StarBlog - (11) 實現訪問統計
基于.NetCore開發博客項目 StarBlog - (12) Razor頁面動態編譯
基于.NetCore開發博客項目 StarBlog - (13) 加入友情鏈接功能
基于.NetCore開發博客項目 StarBlog - (14) 實現主題切換功能
基于.NetCore開發博客項目 StarBlog - (15) 生成隨機尺寸圖片
基于.NetCore開發博客項目 StarBlog - (16) 一些新功能 (監控/統計/配置/初始化)
基于.NetCore開發博客項目 StarBlog - (17) 自動下載文章里的外部圖片
基于.NetCore開發博客項目 StarBlog - (18) 實現本地Typora文章打包上傳
5參考資料
https://www.cnblogs.com/liguix/p/11883248.html