最近在做毕设,遇到了一个场景就是,视频上传。
视频是比较大的,肯定需要分片上传接着合并(后面写篇文章分享下分片上传吧),然后还需要一个功能是删除掉合并的文件
先声明一下,我是用 EggJS 来做服务端的。
好,当我写完代码逻辑之后呢,我走一遍流程试试看行不行
分片上传视频 ==> 合并视频并删除分片 ==> 删除合并视频
OK,第一二部是没有问题的,第三部问题就来了
我想要做的是删除一整个文件夹,正常删除一个非空文件夹,肯定是需要递归目录删除的(暂且不提别的方法)
删除的时候报了以下错误( directory not empty ):
可是,我另起一个demo试着删除,node_module都能删除,这个删除逻辑是没有错的啊
然后回去目录去看发现...........那个合并视频的文件原来还在,那就奇怪了呀
于是我手动删除删除这个文件,删不掉,说需要管理员权限才可以删除,TMD,老子不是最大的还你最大啊~~
上一下图
这个是服务端还没执行删除操作时文件的状态:
接下来是服务端已经执行删除操作的文件状态:
没办法,我只能用更流氓的办法干掉他(某些杀毒软件的删除功能)
到这里,我看了一篇帖子,链接在这里,说是资源管理器还占用着文件,开始我还不是很明白,因为他也没有给出任何的解决方案,所以我也没有太过在意,但这个是解决问题的关键,且看下文
一脸懵逼的我开始怀疑是不是我的删除姿势错了,于是我换了另一种删除方法,rimraf
我起了一个demo试试能不能删除,没有问题,还挺爽呢,几行代码就全删了,舒服
然后我同样把它放到我的服务端代码里面运行
不出意外,还是报错了( operation not permitted ):
不给我操作,我可是你主人啊,我连动你的权利都没了吗????
目录下的文件依然存在,状态跟上面的还是一样
接着我觉得是不是rimraf不够牛逼,删不掉呢,所以换了另一种差不多的方法去解决,node-cmd
虽然用cmd命令行去解决有点原始,但感觉只能用一些原生态的方法才能让这个window适应下我的操作
OK,跟上面一样,demo一时爽,到服务端还是出现一样的问题
这个时候我已经总结到了,这个文件删不掉,一整个文件夹就不可能删掉,我的目标是先干掉这个文件
转折点来了
在我偶然 ctrl+s 保存一下之后,egg的worker进程重启,我发现原来怎么也删除不掉的文件不见了,消失了。。
我就想怎么删除个文件都会延迟一下呢,还需要我重启一下进程。。
但没有办法,我只能寄往这个重启进程了
于是我了解了EggJs的多进程架构,看有没有办法让我重启这个进程
const worker = cluster.worker;
worker.disconnect();
当时天真的我认为worker辣鸡,小老弟,你扎回事,叫你删个文件而已啊,有这么累吗,还没删完就累瘫了,还要我 disconnect 重新招一个worker进来,还是不管了,能干活就行
利用这个重启egg进程的办法,不太稳定,还是删不掉,而且控制台显示 current worker 的那个数组被我添加了越来越多的元素,感觉是不是这个worker招太多了,这招不行啊,于是放弃了这个....不是方法的方法
在我近乎到达绝路的时候,今天一早起床,我冷静的思考一番
分片视频我是可以删除的,那为什么这个合并的视频不能呢?
是不是合并的时候出了什么问题
const targetStream = fs.createWriteStream(fileName);
const readStream = function(chunkArray) {
const path = chunkArray.shift()
const originStream = fs.createReadStream(path);
originStream.pipe(targetStream, { end: false });
originStream.on('end', function() {
// 删除文件
fs.unlinkSync(path);
if (chunkArray.length > 0) {
readStream(chunkArray);
}
});
};
能发现什么吗?没有关闭读写流(:(:(:(:(:(:
const targetStream = fs.createWriteStream(fileName);
const readStream = function(chunkArray) {
const path = chunkArray.shift()
const originStream = fs.createReadStream(path);
originStream.pipe(targetStream, { end: false });
originStream.on('end', function() {
// 删除文件
fs.unlinkSync(path);
if (chunkArray.length > 0) {
readStream(chunkArray);
} else {
targetStream.close();
originStream.close();
}
});
};
(:(:(:(:(:(:
读写流还占着这个文件,删不掉,真的如那篇帖子所讲,资源管理器被占用了,没法操作
总结:
① node删除非空文件夹的方法:
1. 递归目录
2. rimraf
3. node-cmd
② 读写文件一定要关流
③ 写文件一定要关流
④ 文件一定要关流
⑤ 件一定要关流
⑥ 一定要关流
⑦ 定要关流
⑧ 要关流
⑨ 关流
⑩ 卒~~~~~~