refactor: 统一临时文件清理逻辑

This commit is contained in:
2026-06-01 18:29:24 +08:00
parent c061b66169
commit 118c5b1ab7
4 changed files with 21 additions and 20 deletions
+3 -8
View File
@@ -1,5 +1,4 @@
import re import re
from contextlib import suppress
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
@@ -12,17 +11,13 @@ from starlette.background import BackgroundTask
from app import state from app import state
from app.config import CACHE_DIR from app.config import CACHE_DIR
from app.database import DatabaseManager from app.database import DatabaseManager
from app.utils.files import remove_file_safely
router = APIRouter(tags=["database"]) router = APIRouter(tags=["database"])
INVALID_SHEET_NAME_CHARS = re.compile(r"[:\\/?*\[\]]") INVALID_SHEET_NAME_CHARS = re.compile(r"[:\\/?*\[\]]")
def _remove_file(path: Path) -> None:
with suppress(OSError):
path.unlink()
def _resolve_requested_tables( def _resolve_requested_tables(
table_name: Optional[str], table_name: Optional[str],
table_names: Optional[list[str]], table_names: Optional[list[str]],
@@ -227,12 +222,12 @@ async def download_table(
df.to_excel(writer, sheet_name=_make_sheet_name(name, used_sheet_names), index=False) df.to_excel(writer, sheet_name=_make_sheet_name(name, used_sheet_names), index=False)
media_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" media_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
except Exception: except Exception:
_remove_file(filepath) remove_file_safely(filepath)
raise raise
return FileResponse( return FileResponse(
path=str(filepath), path=str(filepath),
filename=filename, filename=filename,
media_type=media_type, media_type=media_type,
background=BackgroundTask(_remove_file, filepath), background=BackgroundTask(remove_file_safely, filepath),
) )
+5 -11
View File
@@ -1,5 +1,4 @@
import zipfile import zipfile
from contextlib import suppress
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@@ -10,17 +9,12 @@ from starlette.background import BackgroundTask
from app import state from app import state
from app.config import CACHE_DIR from app.config import CACHE_DIR
from app.utils.files import format_size, get_dir_size from app.utils.files import format_size, get_dir_size, remove_file_safely
router = APIRouter(tags=["history"]) router = APIRouter(tags=["history"])
def _remove_file(path: Path) -> None:
with suppress(OSError):
path.unlink()
def _safe_filename_part(value: str) -> str: def _safe_filename_part(value: str) -> str:
safe = "".join(char if char.isalnum() or char in {"-", "_"} else "_" for char in value) safe = "".join(char if char.isalnum() or char in {"-", "_"} else "_" for char in value)
return safe.strip("_") or "history" return safe.strip("_") or "history"
@@ -202,14 +196,14 @@ async def download_history(record_id: str = Body(..., embed=True)):
try: try:
_zip_directory(work_dir, archive_path) _zip_directory(work_dir, archive_path)
except Exception: except Exception:
_remove_file(archive_path) remove_file_safely(archive_path)
raise raise
return FileResponse( return FileResponse(
path=str(archive_path), path=str(archive_path),
filename=filename, filename=filename,
media_type="application/zip", media_type="application/zip",
background=BackgroundTask(_remove_file, archive_path), background=BackgroundTask(remove_file_safely, archive_path),
) )
@@ -238,12 +232,12 @@ async def download_history_file(
try: try:
_zip_history_item(target_path, archive_path) _zip_history_item(target_path, archive_path)
except Exception: except Exception:
_remove_file(archive_path) remove_file_safely(archive_path)
raise raise
return FileResponse( return FileResponse(
path=str(archive_path), path=str(archive_path),
filename=filename, filename=filename,
media_type="application/zip", media_type="application/zip",
background=BackgroundTask(_remove_file, archive_path), background=BackgroundTask(remove_file_safely, archive_path),
) )
+7 -1
View File
@@ -1,6 +1,13 @@
from pathlib import Path from pathlib import Path
def remove_file_safely(path: Path) -> None:
try:
path.unlink()
except OSError:
pass
def get_dir_size(path: Path) -> int: def get_dir_size(path: Path) -> int:
total_size = 0 total_size = 0
try: try:
@@ -26,4 +33,3 @@ def format_size(size_bytes: int) -> str:
return f"{value:.2f} {unit}" return f"{value:.2f} {unit}"
value /= 1024.0 value /= 1024.0
return f"{value:.2f} PB" return f"{value:.2f} PB"
+6
View File
@@ -632,3 +632,9 @@
- `app/api/routers/task_runtime.py` centralizes shared task-stage updates, processing license log output, and safe history-retention cleanup for manual processing and remote processing routes. - `app/api/routers/task_runtime.py` centralizes shared task-stage updates, processing license log output, and safe history-retention cleanup for manual processing and remote processing routes.
- `app/api/routers/tasks.py` and `app/api/routers/remote.py` now reuse the shared helpers instead of carrying duplicate `_set_task_stage` and `_log_license_check` implementations. - `app/api/routers/tasks.py` and `app/api/routers/remote.py` now reuse the shared helpers instead of carrying duplicate `_set_task_stage` and `_log_license_check` implementations.
- Verification performed: `.venv\Scripts\python.exe -m compileall app`, `npm run build`, and `cargo check --manifest-path src-tauri\Cargo.toml` with a temporary sidecar placeholder all passed. Generated build output, Python caches, and temporary Tauri sidecar files were removed after verification. - Verification performed: `.venv\Scripts\python.exe -m compileall app`, `npm run build`, and `cargo check --manifest-path src-tauri\Cargo.toml` with a temporary sidecar placeholder all passed. Generated build output, Python caches, and temporary Tauri sidecar files were removed after verification.
## 2026-06-01: Download cleanup helper
- `app/utils/files.py` now provides `remove_file_safely()` for best-effort temporary file cleanup.
- Database table export and history archive download routes now reuse this helper instead of carrying duplicate private `_remove_file()` functions.
- Verification performed: `.venv\Scripts\python.exe -m compileall app`, `npm run build`, and `cargo check --manifest-path src-tauri\Cargo.toml` with a temporary sidecar placeholder all passed. Generated build output, Python caches, and temporary Tauri sidecar files were removed after verification.