Spaces:
Sleeping
Sleeping
| """ | |
| 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 | |