uploadkit-fastapi
FastAPI integration for UploadKit.
What problem does this solve?
Adapts Starlette/UploadFile for sync and async UploadKit stacks, bridges BackgroundTasks into Core after_upload, and maps exceptions to JSON responses — without reimplementing validation or storage.
When to use it
Use when your FastAPI app uploads files through UploadKit Core (Uploader or AsyncUploader).
When not to use it
Do not put validators, policies, or storage implementations in this package. Supply your own sync or async storage (boto3 / aioboto3 → AWS S3 or MinIO).
Choose sync or async
| Async streaming | Sync | |
|---|---|---|
| Entry | AsyncUploader |
Uploader |
| File adapter | as_async_source(file) |
as_uploadable(file) |
| Validators | async_validators=default_async_validators() |
validators=default_validators() |
| Storage | AsyncS3Storage (aioboto3) |
Boto3S3Storage (boto3) |
In an async def route |
await AsyncUploader(...).upload(...) |
await run_sync_upload(...) |
Installation
Requires Python 3.10+ and FastAPI 0.110+.
pip install uploadkit-fastapi uploadkit-security
uv add uploadkit-fastapi uploadkit-security
poetry add uploadkit-fastapi uploadkit-security
Storage samples (not package deps):
pip install boto3 # sync
pip install aioboto3 # async
Storage providers (AWS S3 and MinIO)
Copy the canonical Boto3S3Storage / AsyncS3Storage implementations from the
uploadkit Core README
(or the snippets below). AWS: omit endpoint_url. MinIO: set endpoint_url.
Sync — Boto3S3Storage
import boto3
from botocore.client import Config
class Boto3S3Storage:
def __init__(self, *, access_key, secret_key, region="us-east-1", endpoint_url=None):
kwargs = dict(
service_name="s3",
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
region_name=region,
config=Config(signature_version="s3v4"),
)
if endpoint_url:
kwargs["endpoint_url"] = endpoint_url
self.client = boto3.client(**kwargs)
def put(self, *, bucket, object_name, body, content_type):
resp = self.client.put_object(
Bucket=bucket, Key=object_name, Body=body, ContentType=content_type
)
return resp.get("ETag")
# AWS
boto3_storage = Boto3S3Storage(access_key="AKIA...", secret_key="...", region="eu-west-1")
# MinIO
boto3_storage = Boto3S3Storage(
endpoint_url="http://127.0.0.1:9000",
access_key="minioadmin",
secret_key="minioadmin",
)
Async — AsyncS3Storage (multipart)
Use the full AsyncS3Storage + AsyncS3Writer from the
Core README
(5 MiB part buffering). Construction:
# AWS
async_storage = AsyncS3Storage(access_key="AKIA...", secret_key="...", region="eu-west-1")
# MinIO
async_storage = AsyncS3Storage(
endpoint_url="http://127.0.0.1:9000",
access_key="minioadmin",
secret_key="minioadmin",
)
Async streaming route
from fastapi import BackgroundTasks, FastAPI, UploadFile
from uploadkit import AsyncUploader, UploadPolicy, UploaderError
from uploadkit_fastapi import (
as_async_source,
background_after_upload,
json_error_response,
)
from uploadkit_security import default_async_validators
app = FastAPI()
# async_storage = AsyncS3Storage(...) # AWS or MinIO — see above
def notify(result):
...
@app.post("/upload")
async def upload(file: UploadFile, background_tasks: BackgroundTasks):
policy = UploadPolicy(
max_size=5 * 1024 * 1024,
allowed_extensions=frozenset({"png"}),
allowed_mime_types=frozenset({"image/png"}),
async_validators=default_async_validators(),
)
try:
result = await AsyncUploader(policy, async_storage).upload(
as_async_source(file),
bucket="uploads",
object_name=file.filename or "object",
after_upload=background_after_upload(background_tasks, notify),
# or after_upload=my_celery_task
# or after_upload=sync_notify
)
except UploaderError as exc:
return json_error_response(exc)
return {
"object_name": result.object_name,
"sha256": result.sha256,
"etag": result.etag,
}
Sync stack (boto3) inside an async route
from fastapi import BackgroundTasks, FastAPI, UploadFile
from uploadkit import Uploader, UploadPolicy, UploaderError
from uploadkit_fastapi import (
as_uploadable,
background_after_upload,
json_error_response,
run_sync_upload,
)
from uploadkit_security import default_validators
app = FastAPI()
# boto3_storage = Boto3S3Storage(...) # AWS or MinIO
@app.post("/upload-sync")
async def upload_sync(file: UploadFile, background_tasks: BackgroundTasks):
policy = UploadPolicy(
max_size=5 * 1024 * 1024,
allowed_extensions=frozenset({"png"}),
allowed_mime_types=frozenset({"image/png"}),
validators=default_validators(),
)
try:
result = await run_sync_upload(
Uploader(policy, boto3_storage),
as_uploadable(file),
bucket="uploads",
object_name=file.filename or "object",
after_upload=background_after_upload(background_tasks, notify),
)
except UploaderError as exc:
return json_error_response(exc)
return {"object_name": result.object_name, "sha256": result.sha256}
run_sync_upload runs Uploader.upload in a worker thread.
Sync def route
@app.post("/upload-sync-def")
def upload_sync_def(file: UploadFile, background_tasks: BackgroundTasks):
policy = UploadPolicy(
max_size=5 * 1024 * 1024,
validators=default_validators(),
)
try:
result = Uploader(policy, boto3_storage).upload(
as_uploadable(file),
bucket="uploads",
object_name=file.filename or "object",
after_upload=background_after_upload(background_tasks, notify),
)
except UploaderError as exc:
return json_error_response(exc)
return {"object_name": result.object_name}
After-upload options
Pass Core after_upload on Uploader.upload / AsyncUploader.upload. The hook runs once after a successful put; it does not run on validation/storage failure.
- BackgroundTasks —
background_after_upload(background_tasks, notify)schedulesnotifyafter the response is sent. Prefer this for fire-and-forget work in FastAPI routes. - Celery-like — object with
.delay(**kwargs); Core callsdelay(**result.as_task_kwargs())before returning. - Plain callback — sync
(result) -> None, orasync defon the async stack (awaited). Exceptions from a plain callback propagate and fail the request.
# Celery-like (sync or async stack)
result = await AsyncUploader(policy, async_storage).upload(
as_async_source(file),
bucket="uploads",
object_name=file.filename or "object",
after_upload=process_upload, # process_upload.delay(**as_task_kwargs())
)
Full Core semantics: uploadkit Core README.
Public API
| Symbol | Kind |
|---|---|
as_uploadable |
Sync UploadFile → UploadableFile |
as_async_source |
UploadFile → AsyncByteSource |
background_after_upload |
Core hook via FastAPI BackgroundTasks |
run_sync_upload |
asyncio.to_thread around sync Uploader.upload |
json_error_response / status_for_error / error_payload |
Public |
Changelog
See CHANGELOG.md.
Contributing
See CONTRIBUTING.md.
Metadata
Release files for uploadkit-fastapi 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| uploadkit_fastapi-0.1.1.tar.gz | 10.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| uploadkit_fastapi-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.8 kB
Release files / uploadkit_fastapi-0.1.1.tar.gz
| Download URL | uploadkit_fastapi-0.1.1.tar.gz |
|---|---|
| Size | 10.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6460afb7b2740976748d87cab5a289dcf7332c025654a77da94314b77f86734e
|
|
BLAKE2b-256 checksum How to use checksums |
9c218d6c71029fad6780338933770874a1dc4157b9d4f21818603e1c708ece34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / uploadkit_fastapi-0.1.1-py3-none-any.whl
| Download URL | uploadkit_fastapi-0.1.1-py3-none-any.whl |
|---|---|
| Size | 10.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8ca3b647c08417afc4f427c36660584ee93f91fbcb06f1e6de6ec31d8896ccd2
|
|
BLAKE2b-256 checksum How to use checksums |
5a193a0ef44bb55df2fe27473cbc62713f0eb2fb00ea8ca49511e968ff61cf27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for uploadkit-fastapi 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.