Сервис для хранения файлов аудио, индексации файлов, записи и выдачи результатов распознавания
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

155 lines
4.4 KiB

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