import os import uuid import shutil from datetime import datetime from typing import Optional from fastapi import APIRouter, HTTPException, UploadFile, File, Form import logging logger = logging.getLogger('app') from utils.fastapi_utils import get_versioned_filename router = APIRouter() @router.post("/api/v1/upload") async def upload_file(file: UploadFile = File(...), folder: Optional[str] = Form(None)): """ File upload API endpoint that uploads files to the ./projects/uploads/ directory. You can specify a custom folder name. If omitted, a date-based folder is used. When a folder is specified, the original filename is used and version control is supported. Args: file: Uploaded file folder: Optional custom folder name Returns: dict: Response containing file path and folder information """ try: # Debug information logger.info(f"Received folder parameter: {folder}") logger.info(f"File received: {file.filename if file else 'None'}") # Determine the upload folder if folder: # Use the specified custom folder target_folder = folder target_folder = os.path.basename(target_folder) else: # Get the current date and format it as YYYYMMDD current_date = datetime.now() target_folder = current_date.strftime("%Y%m%d") # Create upload directory upload_dir = os.path.join("projects", "uploads", target_folder) os.makedirs(upload_dir, exist_ok=True) # Process filename if not file.filename: raise HTTPException(status_code=400, detail="Filename cannot be empty") # Parse filename and extension original_filename = file.filename name_without_ext, file_extension = os.path.splitext(original_filename) # Choose naming strategy based on whether a folder is specified if folder: final_filename, version = get_versioned_filename(upload_dir, name_without_ext, file_extension) file_path = os.path.join(upload_dir, final_filename) # Save file with open(file_path, "wb") as buffer: shutil.copyfileobj(file.file, buffer) return { "success": True, "message": f"File uploaded successfully{' (version: ' + str(version) + ')' if version > 1 else ''}", "file_path": file_path, "folder": target_folder, "original_filename": original_filename, "version": version } else: # Use UUID unique filename (original logic) unique_filename = f"{uuid.uuid4()}{file_extension}" file_path = os.path.join(upload_dir, unique_filename) # Save file with open(file_path, "wb") as buffer: shutil.copyfileobj(file.file, buffer) return { "success": True, "message": "File uploaded successfully", "file_path": file_path, "folder": target_folder, "original_filename": original_filename } except HTTPException: raise except Exception as e: logger.error(f"Error uploading file: {str(e)}") raise HTTPException(status_code=500, detail=f"File upload failed: {str(e)}")