Quick Start¶
This guide walks you through building your first file upload endpoint with filestore.
1. Create a FastAPI App¶
app.py
from fastapi import Depends, FastAPI
from filestore import LocalStorage, Store
app = FastAPI()
# Configure a storage instance
storage = LocalStorage(
name="file", # HTML form field name
required=True, # Reject requests with no files
config={
"destination": "uploads", # Directory to write files to
"base_url": "/media", # Public URL prefix
},
)
@app.post("/upload")
async def upload(store: Store = Depends(storage)):
"""Accept a single file upload."""
file_data = store.first("file")
return {
"status": store.status,
"filename": file_data.filename,
"path": str(file_data.path),
"url": file_data.url,
"size": file_data.size,
}
2. Run It¶
3. Test It¶
What Happened?¶
- FastAPI parsed the multipart request and extracted the
filefield - filestore validated the upload (size, type, etc.)
- The file was written atomically to
uploads/document.pdf - If
document.pdfalready existed, it was automatically renamed todocument-1.pdf - A
Storeobject was returned with all the results
Adding Validation¶
Let's restrict uploads to images under 5 MB:
app.py
from filestore import Config, LocalStorage
storage = LocalStorage(
name="image",
required=True,
config=Config(
destination="uploads/images",
base_url="/media/images",
allowed_extensions=[".jpg", ".jpeg", ".png", ".webp"],
allowed_content_types=["image/jpeg", "image/png", "image/webp"],
max_file_size=5 * 1024 * 1024, # 5 MB
),
)
Now any file that doesn't match the constraints will be rejected with a clear error message in store.errors.
Switching Backends¶
The beauty of filestore is that every backend shares the same API. To switch from local to S3:
# Before: local storage
from filestore import LocalStorage
storage = LocalStorage(name="file", config={"destination": "uploads"})
# After: S3 storage
from filestore import S3Storage
storage = S3Storage(
name="file",
config={
"destination": "uploads",
"AWS_BUCKET_NAME": "my-bucket",
"AWS_DEFAULT_REGION": "us-east-1",
},
)
Your endpoint code doesn't change at all.
Next Steps¶
- Storage Backends — Learn about all five backends in detail
- Validation — File size, extensions, content types, and custom filters
- Callbacks — Dynamic filenames, destinations, and metadata
- Multi-Field Uploads — Handle multiple upload fields per request