一、前情提要
有的时候需要导入很多文件,这个时候用思源的文档树去导入又会有点难搞,所以这回我们来弄一个监听文件夹自动导入 markdown 的功能。
二、实现原理和过程
1、nodejs 的 fs
模块
fs 模块能够监听某个文件夹的变动来执行操作,这个之前用来监听代码片段目录自动刷新文档的时候用过了,可以参考这里:
fs.watch 监听文件或目录的更改 - 简书 (jianshu.com)
2、md5 判定是否重复文件
同时通过通过 MD5 和文件名来判断文件是否已经导入过,有关这部分的实现可以参考:
Nodejs 进阶:MD5 入门介绍及 crypto 模块的应用 - 程序猿小卡 - 博客园 (cnblogs.com)
加上文件名是为了减少误判的概率。
3、其他思路和可能的优化方向
可以在每次软件启动时通过导入 markdown 文件夹接口来实现自动导入,这里使用创建文件接口主要是为了方便实现监听文件夹内容来自动导入(因为导入 markdown 文件夹之后会自动重建索引拖慢导入过程)。
主要可能的优化方向有
-
配置项目
- 监听文件夹位置配置
- 监听文件类型位置配置
- 自动导入前置处理与后置处理配置
-
更多的导入格式
- 可以使用上传文件接口实现自动导入附件和.sy.zip 等格式
4、参考
主要参考了 eagle 的监听文件夹自动导入功能。
5、代码实现
const fs = require("fs")
const path = require('path')
let 已导入文件 = []
let 监听目录 = 'C:\\Users\\al765\\Desktop\\markdown'
let 已导入文件列表路径 = path.join(监听目录,'imported.imp')
if(fs.existsSync(已导入文件列表路径)){
已导入文件=JSON.parse(fs.readFileSync(已导入文件列表路径,'utf-8'))
}
let 文件列表 = fs.readdirSync(监听目录)
for (let 文件名 of 文件列表){
let 文件路径 = path.join(监听目录, 文件名)
文件名.endsWith('.重复导入')&&fs.existsSync(文件路径)?fs.rmSync(文件路径):null
}
async function 导入所有markdown() {
let 文件列表 = fs.readdirSync(监听目录)
for await (let 文件名 of 文件列表){
let 文件路径 = path.join(监听目录, 文件名)
if (文件路径.endsWith('.md')&&fs.existsSync(文件路径)&&!是否文件夹(文件路径)){
let 文件内容 = fs.readFileSync(文件路径,'utf-8')
let md5 = require('crypto').createHash('md5')
//通过文件名和内容计算md5来判断文件是否已经导入过
//否则每次黏贴文件会重复触发
//不过这里也可以改成不持久化文件列表,只阻止单次导入过程中重复导入
let 识别码 =md5.update(文件路径+文件内容.replace('.重复导入','')).digest('hex')
if(已导入文件.indexOf(识别码)===-1){
已导入文件.push(识别码)
await 快速导入markdown文件(文件路径,文件名)
}
else{
//这里不删除而是重命名是为了留一个反悔的机会
fs.renameSync(文件路径,文件路径+'.重复导入')
}
}
}
fs.writeFileSync(已导入文件列表路径,JSON.stringify(已导入文件),'utf-8')
}
function 是否文件夹(文件路径) {
let stat = fs.lstatSync(文件路径)
return stat.isDirectory()
}
async function 快速导入markdown文件(文件路径,文件名) {
if (!文件路径.endsWith('.md')||!fs.existsSync(文件路径)) {
return
}
else {
let 文件内容 = fs.readFileSync(文件路径,'utf-8')
let data= await fetch('api/filetree/createDocWithMd', {
method: 'post',
body: JSON.stringify({
notebook: '20230118090131-82fwpy3',
markdown : 文件内容,
path:'/'+文件名.substring(0,文件名.lastIndexOf('.'))
})
})
let res = await data.json()
res.code==0&&fs.existsSync(文件路径)?fs.rmSync(文件路径):null
}
}
fs.watch('C:\\Users\\al765\\Desktop\\markdown',(type,name)=>{
name!=='imported.imp'&&!name.endsWith('.重复导入')?setTimeout(导入所有markdown,1000) :null
})
导入所有markdown()
6、建议应用方向
适合用于主题功能或者代码片段,不太适合做成挂件。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于