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

问题描述 投票:0回答:2

我有一个聊天应用程序,用户可以在其中互相发送文件。每个文件必须在 2 天后删除。

为此,我每 4 小时递归检查一次所有文件,并删除创建时间超过 2 天的文件。

但是这项工作消耗了我服务器的大量CPU,从而扰乱了应用程序的工作。因为要检查的文件数量非常多,全部大小都在10GB左右。

现在,如果每个文件一上传,就激活一个计时器,在 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);
    }
}
javascript node.js file server timer
2个回答
2
投票

现在,如果每个文件一上传,就激活一个计时器,在 2 天后删除该文件,是不是更好?

“更好”是一个难以捉摸的概念,但请考虑一下如果您的服务器崩溃并重新启动,或者您必须关闭它以进行升级等会发生什么:这些计时器丢失了,您必须再次执行目录遍历操作。

这看起来像是一个简单数据库的应用程序。它可以是由文件支持的进程内数据库(例如

sqlite
数据库),或者现在让正确的数据库进程运行也非常简单。您在上传时记录文件的日期/时间和路径,然后定期查询数据库以查看确切的文件已过期并需要删除。无需目录遍历。如果使用单独的数据库(而不是进程内),清理甚至可以是一个单独的过程,如 A R K 建议,而不是占用服务器的主 Node.js 线程。


0
投票

执行目录walkm,但不要重新发明轮子。例如使用 gnu find:

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

从 cron 运行它。

© www.soinside.com 2019 - 2024. All rights reserved.