fastapi-crudrouter icon indicating copy to clipboard operation
fastapi-crudrouter copied to clipboard

How to upload a file using fastapi-crudrouter ?

Open slamer59 opened this issue 4 years ago • 5 comments

Hello, First of all, I am not an expert of FastAPI... so it might not be related at all to fastapi-crudrouter.

I have Pydantic class which holds file metadata:

from pydantic import BaseModel, Field, validator
from fastapi import FastAPI
from fastapi_crudrouter import MemoryCRUDRouter as CRUDRouter

class File(BaseModel):
    FileSize: Optional[ByteSize]
    absolute_path: FilePath

    def __init__(self, *args, **kwargs: Any):
        super().__init__(**kwargs)
        # Size, creationalidator pre
        st = self.absolute_path.stat()
        self.FileSize = st.st_size
        
    @validator("absolute_path")
    def convert_str_to_path(cls, v, values, **kwargs):
        """Convert string to absolute_path
        Returns:
            Path: Absolute path
        """
        if v is None:
            v = values[0]
        if isinstance(v, str):
            v = Path.path(v)
        return v.resolve()
# Works with local file    
# f = File(absolute_path='somefile.py')

# FastAPI with crudrouter
app = FastAPI()
app.include_router(CRUDRouter(schema=File))

I read the documentation to do something like this but I don't know what to put in CreateFile class ?

class CreateFile(BaseModel):
    pass

app.include_router(CRUDRouter(schema=File, create_schema=CreateFile))

In pure FastAPI, upload is done here:

from fastapi import FastAPI, UploadFile
from fastapi import File as FastFile # To not interfear with hand made class name

@app.post('/')
async def upload_file(file: UploadFile = FastFile(...)):
    with open(f'{file.filename}', 'wb') as buffer:
        shutil.copyfileobj(file.file, buffer)

Any ideas if it is possible and how ?

Maybe with this routing functionality ? https://fastapi-crudrouter.awtkns.com/routing

app = FastAPI()
# class CreateFile(BaseModel):
#     pass
router = CRUDRouter(
    schema=File,
    # create_schema=CreateFile
)

router = CRUDRouter(
    schema=File,
    # create_schema=CreateFile
)

@router.post("/file")
async def upload_file(file: UploadFile = FastFile(...)):
    with open(f"{file.filename}", "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    # return ???


app.include_router(router)

Regards

slamer59 avatar Aug 25 '21 14:08 slamer59

The last proposal with router seems to not override the POST method. Any idea ? I don't see an exemple.

slamer59 avatar Aug 25 '21 14:08 slamer59

It's working ! With:

from fastapi.datastructures import UploadFile
from LAPD import Document
from pydantic import BaseModel
from fastapi import FastAPI, UploadFile
from fastapi import File as FastFile
from fastapi_crudrouter import MemoryCRUDRouter as CRUDRouter
from LAPD.core import File
import shutil

app = FastAPI()
router = CRUDRouter(
    schema=File,
)


@router.post("/")
async def upload_file(file: UploadFile = FastFile(...)):
    with open(f"{file.filename}", "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return File(absolute_path=f"{file.filename}")
app.include_router(router)

but why is it working with the path @router.post('') and not @router.post('/file') ?

slamer59 avatar Aug 25 '21 14:08 slamer59

In fact, it is not keep it into memory... Even adding id: int to the attributes.

slamer59 avatar Aug 25 '21 14:08 slamer59

Hi @slamer59, sorry for the delayed response. did you manage to get it working?

awtkns avatar Sep 14 '21 06:09 awtkns

Dont be :) No avance on my side.

slamer59 avatar Sep 14 '21 17:09 slamer59