FastAPI's Form and File Handling: An In - depth Guide

FastAPI is a modern, fast (high - performance) web framework for building APIs with Python based on standard Python type hints. One of the crucial aspects of any web application is handling form data and file uploads. FastAPI provides robust and straightforward mechanisms to handle both form data and file uploads, making it a great choice for developers working on projects that require such functionalities. In this blog post, we will explore the fundamental concepts, usage methods, common practices, and best practices for form and file handling in FastAPI.

Table of Contents

  1. Fundamental Concepts
  2. Handling Form Data
  3. Handling File Uploads
  4. Common Practices
  5. Best Practices
  6. Conclusion
  7. References

Fundamental Concepts

Form Data

In web applications, form data is used to collect information from users through HTML forms. In FastAPI, form data is typically sent using the application/x-www-form-urlencoded or multipart/form-data media types. The Form class in FastAPI is used to handle form data.

File Uploads

File uploads are a common requirement in web applications, such as allowing users to upload profile pictures, documents, etc. FastAPI uses the File class to handle file uploads. When a user uploads a file, the file data is sent as part of a multipart/form-data request.

Handling Form Data

Basic Form Data Retrieval

from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
    return {"username": username, "password": password}

In this example, we define a simple login endpoint that expects two form fields: username and password. The Form(...) indicates that these fields are required.

Using Form in Pydantic Models

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()

class LoginData(BaseModel):
    username: str
    password: str

@app.post("/login-model/")
async def login_model(username: str = Form(...), password: str = Form(...)):
    login_data = LoginData(username=username, password=password)
    return login_data

Here, we use a Pydantic model to structure the form data. This can be useful for more complex data validation and serialization.

Handling File Uploads

Single File Upload

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    contents = await file.read()
    return {"filename": file.filename, "file_size": len(contents)}

In this example, we use the UploadFile class to handle a single file upload. The File(...) indicates that the file is required.

Multiple File Uploads

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile] = File(...)):
    file_sizes = []
    for file in files:
        contents = await file.read()
        file_sizes.append(len(contents))
    return {"filenames": [file.filename for file in files], "file_sizes": file_sizes}

This code allows users to upload multiple files at once. The files parameter is a list of UploadFile objects.

Common Practices

Input Validation

from fastapi import FastAPI, Form
from pydantic import BaseModel, Field

app = FastAPI()

class UserRegistration(BaseModel):
    username: str = Field(min_length=3, max_length=20)
    email: str = Field(regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")

@app.post("/register/")
async def register(username: str = Form(...), email: str = Form(...)):
    user_data = UserRegistration(username=username, email=email)
    return user_data

We use Pydantic’s Field to add validation rules to the form data. This ensures that the input data meets certain criteria.

Error Handling

from fastapi import FastAPI, Form, HTTPException

app = FastAPI()

@app.post("/login-error/")
async def login_error(username: str = Form(...), password: str = Form(...)):
    if not username or not password:
        raise HTTPException(status_code=400, detail="Username and password are required")
    return {"username": username, "password": password}

In this example, we raise an HTTPException if the form data is incomplete.

Best Practices

Security Considerations

  • File Type Validation: When handling file uploads, always validate the file type to prevent malicious files from being uploaded. For example, you can check the file extension or use libraries to verify the file’s MIME type.
from fastapi import FastAPI, File, UploadFile, HTTPException

app = FastAPI()

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.post("/upload-image/")
async def upload_image(file: UploadFile = File(...)):
    if not allowed_file(file.filename):
        raise HTTPException(status_code=400, detail="Invalid file type. Allowed types: png, jpg, jpeg")
    return {"filename": file.filename}
  • Input Sanitization: When dealing with form data, sanitize the input to prevent SQL injection, cross - site scripting (XSS), etc.

Asynchronous File Processing

For large file uploads, it’s recommended to process the files asynchronously to avoid blocking the event loop. FastAPI’s UploadFile class already provides asynchronous methods like read() which can be used to read the file content asynchronously.

import asyncio
from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/upload-large-file/")
async def upload_large_file(file: UploadFile = File(...)):
    async def process_file():
        contents = await file.read()
        # Do some long - running processing here
        await asyncio.sleep(5)
        return len(contents)

    file_size = await process_file()
    return {"filename": file.filename, "file_size": file_size}

Conclusion

FastAPI provides a powerful and easy - to - use set of tools for handling form data and file uploads. By understanding the fundamental concepts, usage methods, common practices, and best practices, developers can build robust and secure web applications that handle user input effectively. Whether it’s a simple login form or a complex file upload feature, FastAPI has got you covered.

References