| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 | import ioimport osimport urllib.parsefrom typing import Optional, Listfrom fastapi import APIRouter, Depends, UploadFile, Form, HTTPException, Queryfrom starlette.responses import StreamingResponsefrom sqlalchemy.ext.asyncio import AsyncSessionfrom app.api.deps import get_async_sessionfrom app.models import Filefrom app.schemas.common import DeleteResponsefrom app.schemas.files import ListFilesResponsefrom app.services.file.file import FileServicerouter = APIRouter()# 限制文件大小max_size = 512 * 1024 * 1024# 支持的文件类型file_ext = [".csv", ".docx", ".html", ".json", ".md", ".pdf", ".pptx", ".txt",            ".xlsx", ".gif", ".png", ".jpg", ".jpeg", ".svg", ".mp3", ".mp4"]@router.get("", response_model=ListFilesResponse)async def list_files(    *,    purpose: Optional[str] = None,    file_ids: Optional[List[str]] = Query(None, alias="ids[]"),    session: AsyncSession = Depends(get_async_session),) -> ListFilesResponse:    """    Returns a list of files that belong to the user's organization.    """    files = await FileService.get_file_list(session=session, purpose=purpose, file_ids=file_ids)    return ListFilesResponse(data=files)@router.post("", response_model=File)async def create_file(    *, session: AsyncSession = Depends(get_async_session), purpose: str = Form(default="assistants"), file: UploadFile) -> File:    """    The size of individual files can be a maximum of 512 MB. See the [Assistants Tools guide]    (/docs/assistants/tools) to learn more about the types of files supported.    """    # 判断后缀名    _, file_extension = os.path.splitext(file.filename)    if file_extension not in file_ext:        raise HTTPException(status_code=400, detail=f"文件类型{file_extension}暂时不支持")    # 判断文件大小    if file.size == 0 or file.size > max_size:        raise HTTPException(status_code=413, detail="File too large")    return await FileService.create_file(session=session, purpose=purpose, file=file)@router.delete("/{file_id}", response_model=DeleteResponse)async def delete_file(*, session: AsyncSession = Depends(get_async_session), file_id: str) -> DeleteResponse:    """    Delete a file.    """    return await FileService.delete_file(session=session, file_id=file_id)@router.get("/{file_id}", response_model=File)async def retrieve_file(*, session: AsyncSession = Depends(get_async_session), file_id: str) -> File:    """    Returns information about a specific file.    """    return await FileService.get_file(session=session, file_id=file_id)@router.get("/{file_id}/content", response_class=StreamingResponse)async def download_file(*, file_id: str, session: AsyncSession = Depends(get_async_session)):    """    Returns the contents of the specified file.    """    file_data, filename = await FileService.get_file_content(session=session, file_id=file_id)    response = StreamingResponse(io.BytesIO(file_data), media_type="application/octet-stream")    response.headers["Content-Disposition"] = f"attachment; filename*=UTF-8''{urllib.parse.quote(filename)}"    response.headers["Content-Type"] = "application/octet-stream"    return response
 |