Welcome to FastAPI Assets! This comprehensive guide will help you install, configure, and start using FastAPI Assets in your FastAPI applications.
- Python 3.10 or higher
- FastAPI 0.115.0 or higher
To install FastAPI Assets with core functionality:
pip install fastapi-assetsFor image validation support:
pip install fastapi-assets[image]For CSV validation support:
pip install fastapi-assets[pandas]For all features:
pip install fastapi-assets[image,pandas]To verify that FastAPI Assets is installed correctly:
import fastapi_assets
print(fastapi_assets.__version__)Here's a minimal FastAPI application with FastAPI Assets:
from fastapi import FastAPI, UploadFile, Depends
from fastapi_assets.validators import FileValidator
app = FastAPI()
# Create a file validator instance
file_validator = FileValidator(
max_size="10MB",
content_types=["image/jpeg", "image/png"]
)
@app.post("/upload/")
async def upload_file(file: UploadFile = Depends(file_validator)):
"""Upload and validate a file."""
return {
"filename": file.filename,
"content_type": file.content_type
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)FileValidator is the foundation for all file validation in FastAPI Assets. Here's how to use it:
from fastapi import FastAPI, UploadFile, Depends
from fastapi_assets.validators import FileValidator
app = FastAPI()
# Create validators for different use cases
profile_photo_validator = FileValidator(
max_size="2MB",
min_size="10KB",
content_types=["image/jpeg", "image/png", "image/gif"],
filename_pattern=r"^[\w\s-]+\.(jpg|jpeg|png|gif)$"
)
document_validator = FileValidator(
max_size="20MB",
content_types=["application/pdf", "application/msword"]
)
@app.post("/upload/profile-photo/")
async def upload_profile_photo(
file: UploadFile = Depends(profile_photo_validator)
):
"""Upload a profile photo with validation."""
return {"filename": file.filename, "size": file.size}
@app.post("/upload/document/")
async def upload_document(
file: UploadFile = Depends(document_validator)
):
"""Upload a document with validation."""
return {"filename": file.filename}For specialized image validation with Pillow:
from fastapi_assets.validators import ImageValidator
app = FastAPI()
image_validator = ImageValidator(
max_size="5MB",
allowed_formats=["JPEG", "PNG"],
min_resolution=(800, 600),
max_resolution=(4000, 4000),
aspect_ratios=["1:1", "16:9"]
)
@app.post("/upload/image/")
async def upload_image(file: UploadFile = Depends(image_validator)):
"""Upload and validate an image file."""
return {"filename": file.filename, "status": "validated"}For CSV file validation with schema checking:
from fastapi_assets.validators import CSVValidator
app = FastAPI()
csv_validator = CSVValidator(
encoding="utf-8",
delimiter=",",
required_columns=["id", "name", "email"],
disallowed_columns=["password"],
min_rows=1,
max_rows=10000
)
@app.post("/upload/csv/")
async def upload_csv(file: UploadFile = Depends(csv_validator)):
"""Upload and validate a CSV file."""
return {"filename": file.filename, "status": "validated"}It's best practice to define validators once and reuse them:
# validators.py
from fastapi_assets.validators import FileValidator, ImageValidator
# Profile images
profile_image_validator = ImageValidator(
max_size="2MB",
allowed_formats=["JPEG", "PNG"],
min_resolution=(200, 200)
)
# Documents
pdf_validator = FileValidator(
max_size="10MB",
content_types=["application/pdf"]
)
# Avatars
avatar_validator = ImageValidator(
max_size="512KB",
allowed_formats=["PNG"],
min_resolution=(64, 64),
max_resolution=(256, 256),
)Then import and use in your routes:
# routes.py
from fastapi import FastAPI, UploadFile, Depends
from .validators import profile_image_validator, pdf_validator, avatar_validator
app = FastAPI()
@app.post("/profile/photo/")
async def update_profile_photo(
file: UploadFile = Depends(profile_image_validator)
):
return {"status": "uploaded"}
@app.post("/submit/document/")
async def submit_document(
file: UploadFile = Depends(pdf_validator)
):
return {"status": "submitted"}
@app.post("/avatar/")
async def upload_avatar(
file: UploadFile = Depends(avatar_validator)
):
return {"status": "updated"}You can combine multiple validators in a single endpoint:
from fastapi_assets.validators import FileValidator, ImageValidator
from fastapi_assets.request_validators import QueryValidator
app = FastAPI()
image_validator = ImageValidator(max_size="5MB")
quality_validator = QueryValidator(
"quality",
_type=str,
allowed_values=["high", "medium", "low"]
)
@app.post("/process/image/")
async def process_image(
file: UploadFile = Depends(image_validator),
quality: str = Depends(quality_validator())
):
"""Process an image with specified quality."""
return {"filename": file.filename, "quality": quality}Customize validation error messages:
file_validator = FileValidator(
max_size="5MB",
min_size="100KB",
content_types=["image/*"],
on_size_error_detail="File must be between 100KB and 5MB",
on_type_error_detail="Only image files are allowed",
on_filename_error_detail="Filename contains invalid characters"
)Use callables for dynamic error messages:
def size_error_message(value):
return f"File size {value} bytes exceeds the limit"
file_validator = FileValidator(
max_size="5MB",
on_size_error_detail=size_error_message
)When validation fails, FastAPI Assets raises HTTPException with appropriate status codes:
# Automatic error handling
@app.post("/upload/")
async def upload_file(file: UploadFile = Depends(file_validator)):
# If validation fails, a 400 error is automatically returned
return {"filename": file.filename}- 400: Bad Request - Validation failed (default)
- 413: Payload Too Large - File exceeds max_size
- 415: Unsupported Media Type - Content type not allowed
file_validator = FileValidator(
max_size="5MB",
status_code=422 # Unprocessable Entity
)from fastapi_assets.request_validators import QueryValidator
app = FastAPI()
page_validator = QueryValidator(
"page",
_type=int,
default=1,
ge=1,
le=1000
)
sort_validator = QueryValidator(
"sort",
_type=str,
allowed_values=["name", "date", "size"],
default="name"
)
@app.get("/items/")
async def list_items(
page: int = Depends(page_validator()),
sort: str = Depends(sort_validator())
):
return {"page": page, "sort": sort}from fastapi_assets.request_validators import HeaderValidator
app = FastAPI()
auth_header_validator = HeaderValidator(
"authorization",
pattern=r"^Bearer [A-Za-z0-9\-._~\+\/]+=*$"
)
@app.get("/protected/")
async def protected_endpoint(
authorization: str = Depends(auth_header_validator())
):
return {"status": "authorized"}from fastapi_assets.request_validators import CookieValidator
app = FastAPI()
session_cookie_validator = CookieValidator(
"session_id",
pattern=r"^[a-f0-9]{32}$"
)
@app.get("/dashboard/")
async def dashboard(
session_id: str = Depends(session_cookie_validator())
):
return {"session": session_id}- Read the API Reference for detailed documentation on all validators
- Check out Examples for real-world use cases
- Explore Custom Validators to create your own validation logic
- Review the Contributing Guide if you want to contribute
Need Help?
- Open an issue on GitHub