NodeJS 如何在2天后自动删除上传的文件

omhiaaxx  于 11个月前  发布在  Node.js
关注(0)|答案(3)|浏览(110)

我有一个聊天应用程序,用户发送文件给对方。每个文件必须在2天后删除。
为此,我每4小时递归检查一次所有文件,并删除那些创建时间超过2天的文件。
但这项工作消耗了我的服务器的CPU,这扰乱了应用程序的工作。因为要检查的文件数量非常大,所有文件的大小约为10 GB。
现在,如果每个文件一上传,一个计时器就被激活,在2天后删除该文件,这是更好的吗?考虑到几乎每秒上传一个文件,计时器的数量可能非常高。
我的递归解决方案:

const fs = require('fs')
const path = require('path')
const rootDir = require('../config').rootDir
const log = require('../da/log');

const DIRECTORY_MESSAGES = rootDir + '/file/messages';
const DIRECTORY_AVATARS = rootDir + '/file/avatars';
const INTERVAL_MINUTES_MESSAGES = 240;
const INTERVAL_MINUTES_AVATARS = 265;
const ACCESS_DAYS_MESSAGES = 2;
const ACCESS_DAYS_AVATARS = 10;
/*
* Remove files that access times is older than {fileAccessHours}.
* Runs every {removeEveryMinutes}
* */
module.exports = {
    start: function () {
        setInterval(deleteFiles.bind(this, DIRECTORY_MESSAGES, ACCESS_DAYS_MESSAGES), INTERVAL_MINUTES_MESSAGES * 60_000)
        setInterval(deleteFiles.bind(this, DIRECTORY_AVATARS, ACCESS_DAYS_AVATARS), INTERVAL_MINUTES_AVATARS * 60_000)
    }
}

function deleteFiles(dir, accessDays) {
    walkDir(dir, function (path, isDirectory) {
        try {
            if (isDirectory) {
                if (path === dir) {
                    return;
                }
                return fs.rmdir(path, function (err) {
                    if (err) {
                        return log.error(__filename + ' :deleteFiles, fs.rmdir, ' + err);
                    }
                });
            } else {
                fs.stat(path, function (err, stat) {
                    try {

                        const now = new Date().getTime();
                        const endTime = new Date(stat.atime).getTime() + accessDays * 86_400_000;
                        if (err) {
                            return log.error(__filename + ' :deleteFiles, fs.stat, ' + err);
                        }
                        if (now > endTime) {
                            return fs.unlink(path, function (err) {
                                if (err) {
                                    return log.error(__filename + ' :deleteFiles, fs.unlink, ' + err);
                                }
                            });
                        }
                    } catch (err) {
                        console.log('File Deleter: walkDir: callback: fs.stat: ' + err);
                    }
                });
            }
        } catch (err) {
            console.log('File Deleter: walkDir: callback' + err);
        }
    });
}

function walkDir(dir, callback) {
    try {
        let files = fs.readdirSync(dir);
        if (files.length === 0) {
            callback(dir, /* isDirectory */ true);
        } else {
            files.forEach(f => {
                let dirPath = path.join(dir, f);
                let isDirectory = fs.statSync(dirPath).isDirectory();
                isDirectory ? walkDir(dirPath, callback) : callback(path.join(dir, f), /* isDirectory */ false);
            });
        }
    } catch (err) {
        console.log('File Deleter: walkDir: ' + err);
    }
}

字符串

x7rlezfr

x7rlezfr1#

现在,如果每个文件一上传,一个计时器就被激活,在2天后删除该文件,这是更好吗?
“更好”是一个不确定的概念,但是考虑一下如果服务器崩溃并重新启动,或者您必须关闭它来升级等情况会发生什么:这些计时器丢失了,您必须再次执行目录遍历。
这看起来像是一个简单数据库的应用程序,它可以是一个由文件支持的进程内数据库(比如sqlite数据库),或者现在,让一个合适的数据库进程运行起来也很简单。你在上传时记录文件的日期/时间和路径,然后定期查询数据库,查看哪些文件已经过期,需要删除。不需要目录遍历。如果使用单独的数据库,(而不是进程内),清理甚至可以像A R K建议的那样是一个单独的进程,而不是捆绑服务器的主Node.js线程。

14ifxucb

14ifxucb2#

做目录walkkm但不要重新发明轮子。例如使用gnu find:

find /path/to/directory -type f -ctime +2 -delete

字符串
从cron上运行。

wqnecbli

wqnecbli3#

  • (从设计Angular 来看,与特定语言无关)*

我会创建一个“”对象的矢量:

struct Expiration
{
    Time expiration_date_and_time; // DDMMYYYY.HHMM
    String full_path;
}

字符串
在上传的每个文件上,向vector的Back添加一个对象,并将vector存储在文件中以进行持久化(崩溃/重启场景)。
一个“Deleter”工作线程,它会休眠直到必须删除向量的Front项,然后进入休眠状态,直到删除下一个项。

重启时:“Deleter”工作线程从文件中加载vector,从vector的Front中删除所有已经过期并进入睡眠状态的项,直到必须删除当前Front为止。

相关问题