修复: 优化文件上传临时文件清理机制
问题描述: - 文件删除操作可能抛出异常导致程序中断 - 服务器崩溃或重启后残留临时文件无法清理 - 没有自动清理机制 修复内容: 1. 添加safeDeleteFile()安全删除函数 - 使用try-catch捕获删除异常 - 记录删除日志和错误信息 - 不会因删除失败而中断主流程 2. 添加cleanupOldTempFiles()定期清理函数 - 启动时自动清理超过24小时的临时文件 - 防止临时文件堆积占用磁盘空间 - 容错处理避免清理失败影响启动 3. 替换所有fs.unlinkSync为safeDeleteFile - 文件大小超限时的临时文件清理 - 上传成功后的临时文件清理 - 上传失败时的临时文件清理 影响范围: 文件上传功能 测试建议: - 上传文件后检查uploads目录临时文件已删除 - 重启服务器验证旧临时文件自动清理 - 模拟删除失败场景验证不影响主流程 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,54 @@ const shareFileCache = new Map();
|
||||
|
||||
// ===== 工具函数 =====
|
||||
|
||||
|
||||
// 安全删除文件(不抛出异常)
|
||||
function safeDeleteFile(filePath) {
|
||||
try {
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log(`[清理] 已删除临时文件: ${filePath}`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[清理] 删除临时文件失败: ${filePath}`, error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 清理旧的临时文件(启动时执行一次)
|
||||
function cleanupOldTempFiles() {
|
||||
const uploadsDir = path.join(__dirname, 'uploads');
|
||||
if (!fs.existsSync(uploadsDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const files = fs.readdirSync(uploadsDir);
|
||||
const now = Date.now();
|
||||
const maxAge = 24 * 60 * 60 * 1000; // 24小时
|
||||
|
||||
let cleaned = 0;
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(uploadsDir, file);
|
||||
try {
|
||||
const stats = fs.statSync(filePath);
|
||||
if (now - stats.mtimeMs > maxAge) {
|
||||
fs.unlinkSync(filePath);
|
||||
cleaned++;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[清理] 检查文件失败: ${filePath}`, err.message);
|
||||
}
|
||||
});
|
||||
|
||||
if (cleaned > 0) {
|
||||
console.log(`[清理] 已清理 ${cleaned} 个超过24小时的临时文件`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[清理] 清理临时文件目录失败:', error.message);
|
||||
}
|
||||
}
|
||||
// SFTP连接
|
||||
async function connectToSFTP(config) {
|
||||
const sftp = new SftpClient();
|
||||
@@ -696,7 +744,7 @@ app.post('/api/upload', authMiddleware, upload.single('file'), async (req, res)
|
||||
if (req.file.size > maxUploadSize) {
|
||||
// 删除已上传的临时文件
|
||||
if (fs.existsSync(req.file.path)) {
|
||||
fs.unlinkSync(req.file.path);
|
||||
safeDeleteFile(req.file.path);
|
||||
}
|
||||
|
||||
return res.status(413).json({
|
||||
@@ -725,7 +773,7 @@ app.post('/api/upload', authMiddleware, upload.single('file'), async (req, res)
|
||||
console.log(`[上传] 文件上传成功: ${remoteFilePath}`);
|
||||
|
||||
// 删除本地临时文件
|
||||
fs.unlinkSync(req.file.path);
|
||||
safeDeleteFile(req.file.path);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
@@ -738,7 +786,7 @@ app.post('/api/upload', authMiddleware, upload.single('file'), async (req, res)
|
||||
|
||||
// 删除临时文件
|
||||
if (fs.existsSync(req.file.path)) {
|
||||
fs.unlinkSync(req.file.path);
|
||||
safeDeleteFile(req.file.path);
|
||||
}
|
||||
|
||||
res.status(500).json({
|
||||
@@ -2154,6 +2202,9 @@ app.get("/s/:code", (req, res) => {
|
||||
res.redirect(frontendUrl);
|
||||
});
|
||||
|
||||
// 启动时清理旧临时文件
|
||||
cleanupOldTempFiles();
|
||||
|
||||
// 启动服务器
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
console.log(`\n========================================`);
|
||||
|
||||
Reference in New Issue
Block a user