存储按用户分目录: storage/用户名/日期/任务ID (物理隔离, 旧数据兼容); 测试断言 admin 目录

This commit is contained in:
lou
2026-08-10 15:31:04 +08:00
parent b79aab5c4e
commit 6b0d163ac0
4 changed files with 12 additions and 6 deletions
+4 -2
View File
@@ -73,8 +73,10 @@ tail -f /tmp/sz-server.log # 实时看
```
data/
├─ app.db SQLite (transfers / files / chunks)
├─ storage/日期/任务ID/ 密文卷目录 (chunk_0001..N, 不合并)
├─ app.db SQLite (users / transfers / files / chunks)
├─ storage/用户名/日期/任务ID/ 密文卷目录 (每用户独立目录, chunk_0001..N, 不合并)
│ admin/ SZ_TOKEN 上传的文件
│ 用户名/ 注册用户上传的文件
└─ tmp/任务ID/ 上传中的卷 (complete 后 move 入 storage)
```
+1 -1
View File
@@ -250,7 +250,7 @@ async def complete(transfer_id: str, request: Request, username: str = Depends(v
"error": f"缺卷: {transfer['chunk_count'] - len(got)} 卷未上传",
})
tasks.set_status(transfer_id, "storing")
final_dir = storage.store_chunks(transfer_id, TMP_ROOT / transfer_id)
final_dir = storage.store_chunks(transfer_id, TMP_ROOT / transfer_id, username)
file_id = db.insert_file(
transfer_id,
transfer["file_name"],
+5 -3
View File
@@ -20,12 +20,14 @@ class Storage:
self.tasks = tasks
self.storage_root = Path(storage_root)
def store_chunks(self, transfer_id: str, chunk_dir: Path) -> Path:
"""卷目录 -> 最终存储目录 (整体 move, 返回目标目录路径)
def store_chunks(self, transfer_id: str, chunk_dir: Path, user_id: str) -> Path:
"""卷目录 -> 用户目录/日期/transfer_id (整体 move, 返回目标目录路径)
每用户独立目录 (user_id 已过注册校验: 3-32 位字母数字/下划线, 无路径风险)。
注意: 目标目录不能预创建, 否则 shutil.move 会嵌套成 dst/dst/。
"""
day_dir = self.storage_root / datetime.now().strftime("%Y-%m-%d")
user_dir = self.storage_root / user_id
day_dir = user_dir / datetime.now().strftime("%Y-%m-%d")
final_dir = day_dir / transfer_id
if final_dir.exists():
raise OSError(f"存储目录已存在: {final_dir}")
+2
View File
@@ -117,6 +117,8 @@ class ServerPipelineTest(unittest.TestCase):
self.assertIsNotNone(row)
chunk_dir = Path(row["path"])
self.assertTrue(chunk_dir.is_dir())
# 每用户独立目录: admin 上传 -> storage/admin/日期/transfer_id
self.assertIn("admin", chunk_dir.parts)
chunk_files_on_disk = sorted(chunk_dir.glob("chunk_*"))
self.assertEqual(len(chunk_files_on_disk), len(chunk_files))
# 卷内容与客户端上传的卷一致