perf(8502): 并行生图(6并发)+超时重试;视频URL直连预览/下载;路径隔离
This commit is contained in:
93
modules/path_utils.py
Normal file
93
modules/path_utils.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Path utilities for cross-session / cross-project isolation.
|
||||
|
||||
Goal:
|
||||
- Avoid file overwrites across concurrent users/projects by namespacing all temp artifacts
|
||||
under temp/projects/{project_id}/...
|
||||
- Provide safe unique filename helpers.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import config
|
||||
|
||||
|
||||
_SAFE_CHARS_RE = re.compile(r"[^A-Za-z0-9._-]+")
|
||||
|
||||
|
||||
def sanitize_filename(name: str) -> str:
|
||||
"""Keep only safe filename characters and strip path separators."""
|
||||
if not isinstance(name, str):
|
||||
return "file"
|
||||
name = name.replace("\\", "_").replace("/", "_").strip()
|
||||
name = _SAFE_CHARS_RE.sub("_", name)
|
||||
return name or "file"
|
||||
|
||||
|
||||
def ensure_dir(path: Path) -> Path:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
def project_root(project_id: str) -> Path:
|
||||
pid = sanitize_filename(project_id or "UNKNOWN")
|
||||
return ensure_dir(config.TEMP_DIR / "projects" / pid)
|
||||
|
||||
|
||||
def project_upload_dir(project_id: str) -> Path:
|
||||
return ensure_dir(project_root(project_id) / "uploads")
|
||||
|
||||
|
||||
def project_images_dir(project_id: str) -> Path:
|
||||
return ensure_dir(project_root(project_id) / "images")
|
||||
|
||||
|
||||
def project_videos_dir(project_id: str) -> Path:
|
||||
return ensure_dir(project_root(project_id) / "videos")
|
||||
|
||||
|
||||
def project_audio_dir(project_id: str) -> Path:
|
||||
return ensure_dir(project_root(project_id) / "audio")
|
||||
|
||||
|
||||
def project_compose_dir(project_id: str, output_name: str) -> Path:
|
||||
out = sanitize_filename(output_name or f"compose_{int(time.time())}")
|
||||
return ensure_dir(project_root(project_id) / "compose" / out)
|
||||
|
||||
|
||||
def unique_filename(
|
||||
prefix: str,
|
||||
ext: str,
|
||||
project_id: Optional[str] = None,
|
||||
scene_id: Optional[int] = None,
|
||||
extra: Optional[str] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Build a unique filename.
|
||||
Example: scene_1_PROJ-xxx_173..._a1b2c3.mp4
|
||||
"""
|
||||
pfx = sanitize_filename(prefix or "file")
|
||||
e = (ext or "").lstrip(".") or "bin"
|
||||
pid = sanitize_filename(project_id) if project_id else None
|
||||
sid = str(int(scene_id)) if scene_id is not None else None
|
||||
ex = sanitize_filename(extra) if extra else None
|
||||
ts = str(int(time.time() * 1000))
|
||||
rnd = uuid.uuid4().hex[:8]
|
||||
parts = [pfx]
|
||||
if sid:
|
||||
parts.append(f"s{sid}")
|
||||
if pid:
|
||||
parts.append(pid)
|
||||
if ex:
|
||||
parts.append(ex)
|
||||
parts.extend([ts, rnd])
|
||||
return f"{'_'.join(parts)}.{e}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user