from fastapi import APIRouter, Depends, HTTPException, UploadFile, File as FastAPIFile, status from fastapi.responses import FileResponse from sqlalchemy.orm import Session from typing import List import os import uuid import aiofiles from apiApp.database import get_db from apiApp.schemas import ( AudioCreate, AudioResponse, AudioListResponse, MessageResponse ) from apiApp.services import AudioCRUD from apiApp.config import UPLOAD_FOLDER, ALLOWED_AUDIO_EXTENSIONS, MAX_UPLOAD_SIZE router = APIRouter() @router.post("/upload", response_model=AudioResponse, status_code=status.HTTP_201_CREATED) async def upload_audio_file( file: UploadFile = FastAPIFile(...), db: Session = Depends(get_db) ): """ Загрузка аудиофайла на сервер """ # Проверка расширения файла file_ext = os.path.splitext(file.filename)[1].lower() if file_ext not in ALLOWED_AUDIO_EXTENSIONS: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=f"File extension not allowed. Allowed: {', '.join(ALLOWED_AUDIO_EXTENSIONS)}" ) # Чтение содержимого файла content = await file.read() # Проверка размера файла if len(content) > MAX_UPLOAD_SIZE: raise HTTPException( status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail=f"File too large. Maximum size: {MAX_UPLOAD_SIZE / (1024*1024)}MB" ) # Сохранение файла file_path = UPLOAD_FOLDER / f"{uuid.uuid4()}{file_ext}" try: async with aiofiles.open(file_path, 'wb') as f: await f.write(content) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error saving file: {str(e)}" ) # Создание записи в БД try: audio_data = AudioCreate(filename=file.filename) audio = AudioCRUD.create( db=db, audio_data=audio_data, file_path=str(file_path), file_size=len(content) ) return audio except Exception as e: # Удаление файла при ошибке записи в БД if os.path.exists(file_path): os.remove(file_path) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error creating database record: {str(e)}" ) @router.get("/audio/list", response_model=AudioListResponse) async def list_audio_files( skip: int = 0, limit: int = 100, db: Session = Depends(get_db) ): """ Получить список всех аудиофайлов """ audios = AudioCRUD.get_all(db) return AudioListResponse( audios=audios[skip:skip+limit], count=len(audios) ) @router.get("/audio/{audio_id}", response_model=AudioResponse) async def get_audio( audio_id: uuid.UUID, db: Session = Depends(get_db) ): """ Получить информацию о аудиофайле по ID """ audio = AudioCRUD.get_by_id(db, audio_id) if not audio: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Audio not found" ) return audio @router.get("/audio/file/{audio_id}") async def download_audio_file( audio_id: uuid.UUID, db: Session = Depends(get_db) ): """ Скачать аудиофайл по ID """ audio = AudioCRUD.get_by_id(db, audio_id) if not audio: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Audio not found" ) if not audio.file_path or not os.path.exists(audio.file_path): raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Audio file not found on disk" ) return FileResponse( path=audio.file_path, filename=audio.filename, media_type='audio/mpeg' ) @router.delete("/audio/delete/{audio_id}", response_model=AudioResponse) async def delete_audio( audio_id: uuid.UUID, db: Session = Depends(get_db) ): """ Удалить аудиофайл """ audio = AudioCRUD.delete(db, audio_id) if not audio: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Audio not found" ) return audio