一、功能场景
electron项目需要实时监听本地/线上文件变化进行差异比对同步文件,因而需要实时监听本地文件变化与线上文件进行比对
二、文件监听库
2.1 fs.watch和 fs.watchFil
watch 和watchFile存在一些系统兼容性问题,具体如下:
fs.watch:
在 MacOS 上不报告文件名。
在 MacOS 上使用像 Sublime 这样的编辑器时根本不报告事件。
经常将事件报告两次。
发出大多数变化作为rename.
不提供递归查看文件树的简单方法。
不支持 Linux 上的递归监视。
fs.watchFile:
在事件处理方面几乎一样糟糕。
也不提供任何递归监视。
导致高 CPU 使用率。
所以选择 Chokidar 为文件监听库 ,Chokidar 库带有一下api:
all: 全部事件
add: 添加文件
addDir: 添加文件夹
change: 文件改变
unlink: 删除文件
unlinkDir: 删除文件夹
Chokidar 提供了一系列的api来反映文件的变化状态,但仍有两张种场景无法准确响应:1. 文件更名 2.文件移动
要解决这两种场景的改变目前有两种思路: 1. 文件更名或者移动的时候是先增加文件然后删除文件,我们可以根据文件操作的时间戳和文件的md5来判断是不是进行了更名或者移动操作。 2. 手动修改chokidar 库来增加这两种场景
三、实现思路
实现思路:
第一步:程序启动时获取本地文件和线上文件进行比对,从而确定那些文件是本地不存在的,即需要下载的文件,那些文件是线上不存在的,即需要上传的文件,比对完成之后分别进行上传和下载操作
将线上文件和本地文件转为格式相同的对象,文件通过md5,文件夹通过路径来比对是否一致,数据结构如下:
fileObj = {
1:[{name:'',path:''}.....],
2:[{name:'',path''}.....],
}
将树形文件数据结构转为对象,同一层级打平为数组,这样操作的好处是当知道某一文件路径,就能快速的定位到文件在哪一层级,只需要循环一次就能查到这条数据,避免树形结构的递归查询
第二步:比对完成之后启动文件监听程序,即 Chokidar 程序,当文件发生变化时,通过api事件类型来区分不同的用户操作进行对应的文件处理
addWatch() {
let watcher = this.watcher
if (watcher) {
watcher.add(this.localPath);
} else {
watcher = chokidar.watch(this.localPath,{ignored: /(^|[/\])../});
watcher.on("all", (event, path) => {
//监听除了ready, raw, and error之外所有的事件类型
console.log(event, path);
});
watcher.on("ready", (path) => {
console.log("ready", path);
});
watcher.on("addDir", (path) => {
console.log("addDir", path);
});
watcher.on("add", (path) => {
console.log("add", path);
});
watcher.on("change", (path) => {
console.log("change", path);
});
watcher.on("unlink", (path) => {
console.log("unlink", path);
});
watcher.on("unlinkDir", (path) => {
console.log("unlinkDir", path);
});
}
}
根据不同的api进行不同的文件操作