How to add both file and JSON body in a FastAPI POST request?
FastAPI is a modern, fast (high-performance), web framework for building APIs. It is based on Python 3.6 and provides a powerful set of tools and features to make the development of APIs easier and more efficient. One of the key features of FastAPI is its support for handling a wide range of request types, including POST requests with files and JSON bodies.
In this article, we will explore how to handle both file and JSON body in a FastAPI POST request. We will cover different methods and provide code examples to simplify the understanding and implementation. Let's get started!
Handling File and JSON Body in FastAPI POST Request
To handle file and JSON body in a FastAPI POST request, you can use the following methods:
Using Form and File: This method allows you to declare multiple Form parameters in a path operation. However, you cannot also declare Body fields that you expect to receive as JSON since the request will have the body encoded using application/x-www-form-urlencoded instead of application/json (when the form includes files, it is encoded as multipart/form-data).
Using Pydantic Models and Dependencies: You can use Pydantic models to inform the endpoint that the parameterised variable depends on the Base class. You can define query parameters directly in the endpoint as demonstrated in this answer.
Passing Body Data as a Single Parameter: Another option is to pass the body data as a single parameter (of type Form) in the form of a JSON string. To that end, you would need to create a dependency function on the server-side.
Using a Custom Class with Classmethod: You can also incorporate a custom class with a classmethod used to transform a given JSON string into a Python dictionary, which is then used for validation against the Pydantic model.
Using Base64-Encoded Files: This method involves converting the file bytes into a base64-format string and adding it to the JSON object, along with other data that you might want to send over to the server. However, this approach is not highly recommended due to the increased size of the file and the additional resources required for encoding and decoding.
Code Examples
Let's explore some code examples to demonstrate how to handle file and JSON body in a FastAPI POST request using different methods:
Method Using Form and File:
from fastapi import Form, File, UploadFile, FastAPI from typing import List from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") @app.post("/submit") def submit( name: str = Form(...), point: float = Form(...), is_accepted: bool = Form(...), files: List[UploadFile] = File(...), ): return { "JSON Payload": {"name": name, "point": point, "is_accepted": is_accepted}, "Filenames": [file.filename for file in files], } @app.get("/", response_class=HTMLResponse) def main(request: Request): return templates.TemplateResponse("index.html", {"request": request})
Method Using Pydantic Models and Dependencies:
from fastapi import Form, File, UploadFile, Request, FastAPI, Depends from typing import List, Optional from fastapi.responses import HTMLResponse from pydantic import BaseModel from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") class Base(BaseModel): name: str point: Optional[float] = None is_accepted: Optional[bool] = False def checker(data: str = Form(...)): try: return Base.model_validate_json(data) except ValidationError as e: raise HTTPException( detail=jsonable_encoder(e.errors()), status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, ) @app.post("/submit") def submit(base: Base = Depends(checker), files: List[UploadFile] = File(...)): return { "JSON Payload": base, "Filenames": [file.filename for file in files], } @app.get("/", response_class=HTMLResponse) def main(request: Request): return templates.TemplateResponse("index.html", {"request": request})
Method Using a Custom Class with Classmethod:
from fastapi import Form, File, UploadFile, FastAPI from typing import List from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") @app.post("/submit") def submit( name: str = Form(...), point: float = Form(...), is_accepted: bool = Form(...), files: List[UploadFile] = File(...), ): return { "JSON Payload": {"name": name, "point": point, "is_accepted": is_accepted}, "Filenames": [file.filename for file in files], } @app.get("/", response_class=HTMLResponse) def main(request: Request): return templates.TemplateResponse("index.html", {"request": request})
With these methods, you have the flexibility to handle file and JSON body in a FastAPI POST request according to your specific requirements. Whether you need to validate data using a Pydantic model or simply receive a JSON string, there is a suitable solution available.
Conclusion
In this article, we have explored various methods to handle both file and JSON body in a FastAPI POST request. By providing code examples and detailed explanations, we have aimed to make the understanding and implementation of these methods as straightforward as possible. As you develop your APIs, you can choose the most appropriate method based on your requirements and preferences.
If
The above is the detailed content of How to Handle File and JSON Body Simultaneously in a FastAPI POST Request?. For more information, please follow other related articles on the PHP Chinese website!