CoolFace
Apppublic

imran-decoder/filecrackhead1

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
file_utils.py80 linesDownload Raw Back to utils
1"""2Temp file management and cleanup utilities.3"""4 5import os6import shutil7import tempfile8import zipfile9from contextlib import contextmanager10from pathlib import Path11from typing import Generator12 13from app.utils.logging_utils import get_logger14 15logger = get_logger(__name__)16 17 18@contextmanager19def temp_conversion_dir() -> Generator[Path, None, None]:20    """21    Context manager that creates a temporary directory for a conversion job22    and guarantees deletion (including all contents) on exit.23    """24    tmp_dir = Path(tempfile.mkdtemp(prefix="fc_"))25    try:26        yield tmp_dir27    finally:28        try:29            shutil.rmtree(tmp_dir, ignore_errors=True)30        except Exception as exc:31            logger.warning("Failed to clean up temp dir %s: %s", tmp_dir, exc)32 33 34def ensure_dir_exists(path: Path) -> None:35    path.mkdir(parents=True, exist_ok=True)36 37 38def zip_directory(source_dir: Path, output_zip: Path) -> Path:39    """40    Zip all files in source_dir into output_zip.41    Used when a conversion produces multiple files (e.g. PDF pages → images).42    """43    with zipfile.ZipFile(output_zip, "w", zipfile.ZIP_DEFLATED) as zf:44        for file_path in sorted(source_dir.iterdir()):45            if file_path.is_file() and file_path.resolve() != output_zip.resolve():46                zf.write(file_path, file_path.name)47    return output_zip48 49 50def get_file_size(path: Path) -> int:51    """Return file size in bytes."""52    return path.stat().st_size53 54 55def safe_output_path(work_dir: Path, stem: str, extension: str) -> Path:56    """Build a safe output path inside the working directory."""57    clean_ext = extension.lstrip(".")58    return work_dir / f"{stem}.{clean_ext}"59 60 61async def save_upload_to_temp(62    upload_file, work_dir: Path, safe_name: str, chunk_size: int = 256 * 102463) -> tuple[Path, int]:64    """65    Stream a FastAPI UploadFile to disk in chunks, avoiding loading the66    entire file into memory at once.67 68    Returns (file_path, total_bytes_written).69    """70    dest = work_dir / safe_name71    total = 072    with open(dest, "wb") as f:73        while True:74            chunk = await upload_file.read(chunk_size)75            if not chunk:76                break77            f.write(chunk)78            total += len(chunk)79    return dest, total80