""" Fallback storage service for when Cloudinary uploads fail. This provides a more controlled way to handle local storage fallback. """ from pathlib import Path from typing import Optional import logging from uuid import uuid4 logger = logging.getLogger(__name__) # Define fallback upload directories FALLBACK_PATHS = [ Path(__file__).resolve().parent.parent / "uploads", Path("/tmp/uploads"), Path("/app/uploads") ] # Find a usable directory FALLBACK_DIR = None for path in FALLBACK_PATHS: try: path.mkdir(exist_ok=True, parents=True) FALLBACK_DIR = path logger.info(f"Fallback storage directory ready: {FALLBACK_DIR}") break except Exception as e: logger.warning(f"Cannot use {path} for fallback storage: {e}") continue if FALLBACK_DIR is None: logger.error("Could not create any fallback storage directory") FALLBACK_DIR = Path("/tmp") # Last resort fallback async def store_file_locally(file_content: bytes, original_filename: str) -> Optional[str]: """ Store a file in the local filesystem as a fallback when cloud storage fails Args: file_content: The binary content of the file original_filename: The original filename Returns: Relative path to the stored file or None if storage failed """ try: # Create a unique filename file_extension = Path(original_filename).suffix filename = f"{uuid4().hex}{file_extension}" file_path = FALLBACK_DIR / filename # Write the file file_path.write_bytes(file_content) logger.info(f"File saved to fallback storage: {file_path}") # Return a relative path that can be used in URLs return str(Path("uploads") / filename) except Exception as e: logger.error(f"Failed to save file to fallback storage: {e}") return None