修复: 优化存储配额检查时机,支持文件覆盖场景

问题描述:
- 上传文件覆盖已有文件时配额检查不准确
- 只检查新文件大小,不考虑旧文件会被删除释放的空间
- 导致误报配额不足,阻止合理的文件覆盖操作
- 空间统计不准确,累积误差

修复内容:
1. 智能配额检查
   - 上传前检测目标文件是否存在
   - 计算净增量(新文件大小 - 旧文件大小)
   - 只在净增量为正时才检查配额
   - 覆盖更小文件时不检查配额

2. 准确的空间更新
   - 使用净增量更新已使用空间
   - 支持负增量(文件变小时减少用量)
   - 避免重复计算导致的累积误差

3. 容错处理
   - try-catch捕获旧文件不存在的情况
   - 确保即使旧文件检查失败也能继续

修复场景示例:
- 配额10GB,已使用9.5GB
- 有一个1GB的旧文件
- 上传0.8GB新文件覆盖
- 修复前: 9.5+0.8=10.3GB > 10GB  拒绝
- 修复后: 9.5-1+0.8=9.3GB < 10GB ✓ 允许

影响范围: 本地存储文件上传功能

测试建议:
- 测试文件覆盖场景配额检查正确
- 验证空间使用统计准确
- 确认新文件上传场景仍正常工作

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-11 14:28:46 +08:00
parent c9553ff497
commit 2a58380b32

View File

@@ -83,9 +83,24 @@ class LocalStorageClient {
async put(localPath, remotePath) { async put(localPath, remotePath) {
const destPath = this.getFullPath(remotePath); const destPath = this.getFullPath(remotePath);
// 检查配额 // 获取新文件大小
const fileSize = fs.statSync(localPath).size; const newFileSize = fs.statSync(localPath).size;
this.checkQuota(fileSize);
// 如果目标文件存在,计算实际需要的额外空间
let oldFileSize = 0;
if (fs.existsSync(destPath)) {
try {
oldFileSize = fs.statSync(destPath).size;
} catch (err) {
// 文件可能已被删除,忽略错误
}
}
// 检查配额:只检查净增量(新文件大小 - 旧文件大小)
const netIncrease = newFileSize - oldFileSize;
if (netIncrease > 0) {
this.checkQuota(netIncrease);
}
// 确保目标目录存在 // 确保目标目录存在
const destDir = path.dirname(destPath); const destDir = path.dirname(destPath);
@@ -108,8 +123,10 @@ class LocalStorageClient {
// 重命名临时文件为目标文件 // 重命名临时文件为目标文件
fs.renameSync(tempPath, destPath); fs.renameSync(tempPath, destPath);
// 更新已使用空间 // 更新已使用空间(使用净增量)
this.updateUsedSpace(fileSize); if (netIncrease !== 0) {
this.updateUsedSpace(netIncrease);
}
} catch (error) { } catch (error) {
// 清理临时文件 // 清理临时文件
if (fs.existsSync(tempPath)) { if (fs.existsSync(tempPath)) {