首页 > 其他分享 >基于.NetCore开发博客项目 StarBlog - (18) 实现本地Typora文章打包上传

基于.NetCore开发博客项目 StarBlog - (18) 实现本地Typora文章打包上传

时间:2022-10-07 00:00:56浏览次数:82  
标签:NetCore 18 Typora 博客 开发 文章 var StarBlog

前言

九月太忙,只更新了三篇文章,本来这个功能是从九月初就开始做的,结果一直拖到现在国庆假期才有时间完善并且写文章~

之前我更新了几篇关于 Python 的文章,有朋友留言问是不是不更新 .Net 了,那肯定不能啊,我只能说「我 全 都 要」,所以我反手就更新了一篇Asp-Net-Core开发笔记

然后顺便立个Flag:今年底前完成StarBlog系列文章的主体部分(即API开发+后台前端开发,目前只完成博客前后端部分),加油吧~

OK,说回本文,程序员都喜欢用Markdown来写文章,但由于markdown是纯文本格式,在其中插入的图片要如何保存,就成了一大烦恼,有人选择图床,但不一定永久有效;有人选择本地存储,图片永久有效,但如何分享文章又成了一个难题…

我选的就是第二种,本地存储。使用Typora写文章,图片保存在和Markdown文件同名的目录(markdown.assets)下,这样可以获得很好的写作体验,然后分享的问题就交给StarBlog吧,这个项目开发的初衷就是为了把本地的文章发表成博客。

不过之前只有批量导入文章的功能,现在我要做的就是单独实现一个单篇文章打包导入的功能。

随着文章越来越多,系列文章的目录放前面有点影响阅读了,所以从这篇开始我把它放到最后面~

实现思路

假设我用Typora写了一篇Markdown文章,文件名为:StarBlog.md,并且在里面插入了若干图片,根据配置,Typora会自动生成一个目录(StarBlog.assets)来存放这些图片。

为了实现导入,我要把这个markdown文件和这个存图片的目录一起打包成zip压缩文件上传,后端将zip压缩包解压到临时目录,读取Markdown文件,解析其中的内容,进行导入操作。

代码实现

OK,开始写代码吧

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

解压缩

首先是解压缩功能,.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 ,在本系列一开始就写过,所以这里就不再当复读机了,可以直接看这两篇文章:

直接上代码了

因为是做单篇文章导入,所以我这里获取临时目录写的所有 *.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);

系列文章

参考资料

标签:NetCore,18,Typora,博客,开发,文章,var,StarBlog
From: https://www.cnblogs.com/deali/p/16758878.html

相关文章

  • 恶意代码分析实战 加壳与脱壳 lab 18-1 18-2 18-3 18-4 18-5
    脱壳存根被加壳程序中的脱壳存根由操作系统加载,然后脱壳存根负载加载原始程序。对于加壳程序来说,可执行程序的入口点指向脱壳存根,而不是原始代码。原始程序通常存储在......
  • 网鼎杯2018----fakebook
    关于前期的信息收集: 源码泄漏user.php.bak和flag.php(如果有机会尝试读取这个文件)这两个有用的。查看源码泄漏中对blog的过滤部分,然后通过join页面随便输入一个符合......
  • 腾讯AI Lab的CVPR 2018文章解读
    今天和大家分享马上要召开的CVPR2018会议,这算殿堂级的会议,今天主要主角是我和腾讯,......
  • CVPR2018 ——(GAN)延时摄影视频的生成
    CVPR2018即将开始,陆陆续续很多优秀的作品被大家知晓。今天我们来说说又去的科研成果,也希望阅读您对此感兴趣~在户外拍摄一张照片之后,我们可以预测照片里面接下来发生的事情......
  • CVPR 2018论文解读 | 学习在黑暗中看世界(Learning to See in the Dark)
    好些天不和大家见面,还是怪想各位关注我们支持我们的你!由于“计算机视觉战队”创始人最近接近毕业阶段,所以很多事情要去处理,没有及时给大家带来好的分享,在此向大家表示由衷的......
  • P4384 [八省联考 2018] 制胡窜
    P4384[八省联考2018]制胡窜考虑先将问题转化为切断两个位置使得没有任何一段中包含\(t\)。则最终的答案为\(\dbinom{n}{2}-\text{ans}\)。计\(t\)按左端点排序后......
  • Ubuntu18.04系统下最新版GPU环境配置详细教程
    摘要:本文详细介绍了在Ubuntu18.04下如何配置深度学习GPU(显卡)环境,包括了显卡驱动下载安装,环境配置等。按照本教程的步骤在多台服务器上安装都取得了成功,是在多种方法的......
  • P1823 [COI2007] Patrik 音乐会的等待
    用单调队列维护即可,注意要考虑高度相同的情况(可以记录单调队列中相同的个数)。时间复杂度为\(O(n)\)。#include<bits/stdc++.h>usingnamespacestd;#defineintlong......
  • *洛谷 P1018 [NOIP2000 提高组] 乘积最大(dfs+高精度)
    说在前头此篇题解是记录自己的暴力写法,并不能100分满分通过洛谷测试数据(只有60)纯纯记录写法而写https://www.luogu.com.cn/problem/P1018我还说这么简单呢这题,想太......
  • 518.coin-change-ii 零钱兑换II
    问题描述518.零钱兑换II解题思路本题依旧是一个完全背包问题,但是本题求的是组合而非排列。求组合时,先遍历物品,再遍历体积;求排列时,则是先遍历体积,再遍历物品。例如:假设......