6.3 KiB
6.3 KiB
上传临时文件清理机制
概述
系统实现了完整的临时文件清理机制,用于清理断点续传、上传失败、用户取消上传等情况产生的临时文件,防止服务器存储空间被占用。
清理场景
1. 自动清理场景
✅ 上传成功后的清理
- 位置:
app/api/materials/upload/route.ts - 时机: 素材成功创建到数据库后
- 清理内容:
- 临时合并文件(
merged-{fileName}) - 空临时目录
- 上传会话记录
- 临时合并文件(
✅ 分片合并后的清理
- 位置:
app/api/materials/upload/complete/route.ts - 时机: 所有分片合并完成后
- 清理内容:
- 所有分片文件(
chunk-{index}) - 保留合并后的文件供正式上传使用
- 所有分片文件(
✅ 上传会话过期清理
- 位置:
lib/upload-sessions.ts - 机制:
- Redis模式: 自动过期(8小时TTL)
- 内存模式: 每小时清理一次过期会话(8小时)
2. 手动清理场景
✅ 用户取消上传
- 位置:
components/UploadModal.tsx→handleCancelBatchUpload() - 触发: 用户点击"取消上传"按钮
- 清理内容:
- 取消所有进行中的HTTP请求
- 调用清理API删除临时文件和上传会话
- 清理前端IndexedDB中的上传状态
✅ 清理API调用
- 位置:
app/api/materials/upload/cleanup/route.ts - 方式:
POST /api/materials/upload/cleanup: 清理指定的上传会话GET /api/materials/upload/cleanup: 清理所有过期的临时文件
3. 定时清理任务
✅ 定时清理脚本
- 位置:
scripts/cleanup-upload-temp.ts - 功能: 清理所有过期或无效的临时上传文件
- 清理条件:
- 上传会话已过期(默认8小时)
- 上传会话不存在(Redis/内存中已删除)
- 运行方式:
# 手动运行 npx tsx scripts/cleanup-upload-temp.ts # 添加到定时任务(建议每小时运行一次) # Linux cron: 0 * * * * cd /path/to/project && npx tsx scripts/cleanup-upload-temp.ts # Windows 任务计划程序: # 创建定时任务,每小时运行一次
临时文件结构
uploads/
└── temp/
└── {uploadId}/
├── meta.json # 元数据文件(包含创建时间等信息)
├── chunk-0 # 分片文件
├── chunk-1
├── ...
└── merged-{fileName} # 合并后的文件(等待正式上传)
清理策略
清理时机
-
立即清理(上传成功后)
- 正式上传成功后立即清理临时合并文件
- 清理上传会话记录
-
用户触发清理(取消上传)
- 用户点击取消时立即清理
- 清理所有相关的临时文件和会话
-
定时清理(过期文件)
- 每小时运行一次清理脚本
- 清理超过24小时的临时文件
- 清理会话不存在的临时文件
清理条件
文件会被清理的条件:
- ✅ 上传会话已过期(默认8小时)
- ✅ 上传会话不存在(Redis/内存中已删除)
- ✅ 用户主动取消上传
- ✅ 上传成功完成
文件不会被清理的条件:
- ❌ 上传会话存在且未过期
- ❌ 正在上传中的文件(有活跃会话)
API 使用说明
清理指定上传会话
// POST /api/materials/upload/cleanup
const response = await fetch('/api/materials/upload/cleanup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ uploadId: 'upload-xxx' }),
})
清理所有过期文件
// GET /api/materials/upload/cleanup?expiredOnly=true&maxAge=24
const response = await fetch('/api/materials/upload/cleanup?expiredOnly=true&maxAge=24')
参数说明:
uploadId(可选): 指定要清理的上传IDexpiredOnly(可选): 是否只清理过期的(默认true)maxAge(可选): 最大年龄(小时),默认24小时
配置说明
环境变量
# 上传目录(临时文件存储位置)
UPLOAD_DIR=./uploads
# 上传会话过期时间(在 upload-sessions.ts 中硬编码为24小时)
# Redis模式:自动过期
# 内存模式:每小时清理一次
清理脚本配置
在 scripts/cleanup-upload-temp.ts 中:
const MAX_AGE_HOURS = 8 // 8小时后清理
监控和日志
清理日志
系统会记录以下清理日志:
[Cleanup] 开始清理临时上传文件...
[Cleanup] 清理上传会话: upload-xxx (过期 25.3小时)
[Cleanup] ✓ 清理成功: 5 个文件, 释放 150.5 MB
[Cleanup] 清理完成:
- 清理文件数: 10
- 释放空间: 500.2 MB
错误处理
- 清理失败不会影响主流程
- 所有清理错误都会被捕获并记录警告日志
- 单个文件清理失败不会阻止其他文件的清理
最佳实践
1. 生产环境部署
建议在生产环境中:
-
启用Redis存储上传会话
- 使用
lib/upload-sessions-redis.ts - 自动过期机制,无需手动清理会话
- 使用
-
设置定时清理任务
- 每小时运行一次
scripts/cleanup-upload-temp.ts - 使用 cron 或系统定时任务
- 每小时运行一次
-
监控存储空间
- 定期检查
uploads/temp/目录大小 - 如果发现异常增长,手动运行清理脚本
- 定期检查
2. 开发环境
- 使用内存Map存储(自动清理过期会话)
- 可以手动调用清理API测试清理功能
故障排查
问题:临时文件占用空间过大
解决方案:
- 检查定时清理任务是否正常运行
- 手动运行清理脚本:
npx tsx scripts/cleanup-upload-temp.ts - 检查上传会话过期时间设置是否合理
问题:清理后文件仍存在
可能原因:
- 文件正在被其他进程使用
- 文件权限问题
- 清理脚本执行失败
解决方案:
- 检查文件是否被锁定
- 检查文件权限
- 查看清理日志中的错误信息
总结
系统实现了完整的临时文件清理机制:
✅ 自动清理: 上传成功后、分片合并后、会话过期后
✅ 手动清理: 用户取消上传时
✅ 定时清理: 每小时清理过期文件
✅ 错误处理: 清理失败不影响主流程
✅ 日志记录: 详细的清理日志便于监控
这确保了服务器存储空间不会被临时文件占用,同时保证了系统的稳定运行。