quota: GET /api/quota (used=files size 总和 / quota 默认 10GB SZ_QUOTA env / remain / percent); 测试 7 项
This commit is contained in:
@@ -25,7 +25,7 @@ from fastapi.responses import FileResponse, JSONResponse
|
||||
|
||||
from db import ServerDB
|
||||
from receiver import Receiver, ReceiverError
|
||||
from settings import STORAGE_ROOT, TMP_ROOT, TOKEN
|
||||
from settings import QUOTA_BYTES, STORAGE_ROOT, TMP_ROOT, TOKEN
|
||||
from storage import Storage
|
||||
from task_manager import TaskManager
|
||||
|
||||
@@ -63,6 +63,19 @@ async def list_files():
|
||||
return {"files": db.list_files()}
|
||||
|
||||
|
||||
@app.get("/api/quota", dependencies=[Depends(verify_token)])
|
||||
async def quota():
|
||||
"""用户空间配额: 已用 (files size 总和) / 配额 / 剩余"""
|
||||
used = db.sum_files_size()
|
||||
remain = max(QUOTA_BYTES - used, 0)
|
||||
return {
|
||||
"used_bytes": used,
|
||||
"quota_bytes": QUOTA_BYTES,
|
||||
"remain_bytes": remain,
|
||||
"percent": round(used * 100 / QUOTA_BYTES, 1) if QUOTA_BYTES else 0,
|
||||
}
|
||||
|
||||
|
||||
@app.delete("/api/files/{file_id}", dependencies=[Depends(verify_token)])
|
||||
async def delete_file(file_id: str):
|
||||
"""删除文件 (卷目录 + 入库记录)"""
|
||||
|
||||
@@ -201,6 +201,12 @@ class ServerDB:
|
||||
cur = conn.execute("DELETE FROM files WHERE file_id = ?", (file_id,))
|
||||
return cur.rowcount > 0
|
||||
|
||||
def sum_files_size(self) -> int:
|
||||
"""全部文件 size 总和 (配额统计用)"""
|
||||
with self._conn() as conn:
|
||||
row = conn.execute("SELECT COALESCE(SUM(size), 0) FROM files").fetchone()
|
||||
return int(row[0])
|
||||
|
||||
def get_file(self, file_id: str) -> dict[str, Any] | None:
|
||||
"""单文件记录 (下载端点, 含解密参数 enc_params + 卷数)"""
|
||||
with self._conn() as conn:
|
||||
|
||||
@@ -17,6 +17,9 @@ STORAGE_ROOT = Path(os.environ.get("SZ_STORAGE_ROOT", "data/storage"))
|
||||
# 临时目录 (分卷/合并中间产物)
|
||||
TMP_ROOT = Path(os.environ.get("SZ_TMP_ROOT", "data/tmp"))
|
||||
|
||||
# 用户空间配额 (已用 = files 表 size 总和, 超配额拒绝新上传? 暂只读展示)
|
||||
QUOTA_BYTES = int(os.environ.get("SZ_QUOTA", str(10 * 1024**3))) # 默认 10GB
|
||||
|
||||
# API 服务
|
||||
HOST = os.environ.get("SZ_HOST", "0.0.0.0")
|
||||
PORT = int(os.environ.get("SZ_PORT", "8000"))
|
||||
|
||||
@@ -237,6 +237,16 @@ class ServerPipelineTest(unittest.TestCase):
|
||||
len(self.client.get("/api/files", headers=AUTH).json()["files"]), before
|
||||
)
|
||||
|
||||
# 配额: 返回结构 + 已用 = files size 总和
|
||||
r = self.client.get("/api/quota", headers=AUTH)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = r.json()
|
||||
self.assertIn("used_bytes", q)
|
||||
self.assertIn("quota_bytes", q)
|
||||
self.assertIn("remain_bytes", q)
|
||||
self.assertEqual(q["used_bytes"], q["quota_bytes"] - q["remain_bytes"])
|
||||
self.assertGreater(q["quota_bytes"], 0)
|
||||
|
||||
# del: 删除后列表减少, 再删 404
|
||||
r = self.client.delete(f"/api/files/{file_id}", headers=AUTH)
|
||||
self.assertEqual(r.status_code, 200, r.text)
|
||||
|
||||
Reference in New Issue
Block a user