1

I'm trying to receive image file for my FastAPI file, upload it to a server and then Save url in database.

My create_product and create_category endpoint works as expected without the file: UploadFile = File(...) passed to the router function

I could successfully upload files with other routes and get their filename but not with the above mentioned routes

Routes:

@router.post('/category/create', response_model=schemas.CategoryOut)
def create_category(*, request: schemas.CategoryIn,  file: UploadFile = File(...),  db: Session = Depends(get_db), current_user: schemas.UserOut = Depends(get_current_active_user)):
    category = storeview.get_category_by_slug(db, request.slug)
    if category:
        raise HTTPException(status.HTTP_400_BAD_REQUEST,
                            detail=f"Category with slug {request.slug} already exists!")
    request.image = storeview.save_file(file)
    return storeview.create_category(db, request)


@router.post('/product/create', response_model=schemas.Product)
async def create_product(*, file: UploadFile = File(...), request: schemas.ProductIn, category_id: int,  db: Session = Depends(get_db), current_user: schemas.UserOut = Depends(get_current_active_user)):
    product = storeview.get_category_by_slug(db, request.slug)
    if product:
        raise HTTPException(status.HTTP_400_BAD_REQUEST,
                            detail=f"Product with slug {request.slug} already exists!")
    request.image = storeview.save_file(file)
    return storeview.create_product(db, request, category_id)

Views:


def create_category(db: Session, request: schemas.CategoryIn):
    new_category = models.Category(
        name=request.name, slug=request.slug, image=request.image)
    db.add(new_category)
    db.commit()
    db.refresh(new_category)
    return new_category


def create_product(db: Session, request: schemas.ProductIn, category_id: int):
    new_product = models.Product(**request.dict(), category_id=category_id)
    db.add(new_product)
    db.commit()
    db.refresh(new_product)
    return new_product


def save_file(file: UploadFile = File(...)):
    result = cloudinary.uploader.upload(file.file)
    url = result.get("url")
    return url

Schemas:

class CategoryBase(BaseModel):
    name: str
    slug: str
    image: str


class Category(CategoryBase):
    id: int

    class Config:
        orm_mode = True


class CategoryIn(CategoryBase):
    pass


class ProductBase(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    image: str
    slug: str


class Product(ProductBase):
    id: int
    category_id: int
    category: Category

    class Config:
        orm_mode = True


class ProductIn(ProductBase):
    pass


class CategoryOut(CategoryBase):
    products: List[Product] = []
    id: int

    class Config:
        orm_mode = True

  • 1
    I don't think you can have `request` and `file` in the same endpoint. Can't you base64 encode the file and send it as part of the request body? In other words, include the file as base64string in the json you are posting to the endpoint. – AndreFeijo Aug 11 '21 at 04:43
  • Ooh.... I didn't know that I would try checking on how I could encode the file with the request – Seyi Oyefeso Aug 11 '21 at 07:02
  • Using base64 and attaching it in a JSON field is usually the way its done; the FileReader API in Javascript has `readAsDataURL` that gives you the file's content pre-encoded in a suitable format. – MatsLindh Aug 11 '21 at 08:56

0 Answers0