
- Modified config.py to use environment variables for storage paths - Added better error handling for directory creation - Updated file_service.py to handle permission errors gracefully - Changed default storage path to './storage' instead of '/app/storage' - Added comprehensive documentation about storage configuration - Added logging for better debugging of file operations - Updated README with storage configuration guidelines
80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
import logging
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
PROJECT_NAME: str = "File Upload Download API"
|
|
API_V1_STR: str = "/api/v1"
|
|
|
|
# Base directory for storage - can be overridden by environment variable
|
|
STORAGE_BASE_DIR: str = os.environ.get("STORAGE_BASE_DIR", "./storage")
|
|
|
|
# File storage directory - derived from base dir but can be overridden
|
|
FILE_STORAGE_DIR: Optional[str] = os.environ.get("FILE_STORAGE_DIR")
|
|
|
|
# Database directory - derived from base dir but can be overridden
|
|
DB_DIR: Optional[str] = os.environ.get("DB_DIR")
|
|
|
|
# Database URL - derived from DB_DIR but can be overridden
|
|
SQLALCHEMY_DATABASE_URL: Optional[str] = os.environ.get("SQLALCHEMY_DATABASE_URL")
|
|
|
|
# Configure max file size (10MB by default)
|
|
MAX_FILE_SIZE: int = int(
|
|
os.environ.get("MAX_FILE_SIZE", 10 * 1024 * 1024)
|
|
) # 10MB in bytes
|
|
|
|
model_config = SettingsConfigDict(case_sensitive=True, env_file=".env")
|
|
|
|
|
|
# Create settings instance
|
|
settings = Settings()
|
|
|
|
# Resolve directory paths if not explicitly set via environment variables
|
|
if not settings.FILE_STORAGE_DIR:
|
|
settings.FILE_STORAGE_DIR = os.path.join(settings.STORAGE_BASE_DIR, "files")
|
|
|
|
if not settings.DB_DIR:
|
|
settings.DB_DIR = os.path.join(settings.STORAGE_BASE_DIR, "db")
|
|
|
|
if not settings.SQLALCHEMY_DATABASE_URL:
|
|
db_path = os.path.join(settings.DB_DIR, "db.sqlite")
|
|
settings.SQLALCHEMY_DATABASE_URL = f"sqlite:///{db_path}"
|
|
|
|
# Convert string paths to Path objects for easier manipulation
|
|
storage_base_path = Path(settings.STORAGE_BASE_DIR)
|
|
db_path = Path(settings.DB_DIR)
|
|
file_storage_path = Path(settings.FILE_STORAGE_DIR)
|
|
|
|
# Try to create directories with better error handling
|
|
try:
|
|
# Ensure base storage directory exists
|
|
storage_base_path.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"Base storage directory: {storage_base_path}")
|
|
|
|
# Ensure DB directory exists
|
|
db_path.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"Database directory: {db_path}")
|
|
|
|
# Ensure file storage directory exists
|
|
file_storage_path.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"File storage directory: {file_storage_path}")
|
|
except PermissionError as e:
|
|
logger.warning(
|
|
f"Permission denied when creating directories: {e}. "
|
|
f"The application may need to be run with appropriate permissions or "
|
|
f"you should pre-create these directories with correct permissions."
|
|
)
|
|
# We'll continue running, as the application might be able to function
|
|
# if the directories already exist with correct permissions
|
|
except Exception as e:
|
|
logger.error(f"Error creating storage directories: {e}")
|
|
# We'll still continue running in case the application can operate
|
|
# without direct file access (e.g., if using external storage)
|