Direct-to-S3 client-side uploads for Django with multipart support, pause/resume, and file management APIs.
Project description
django-s3-upload
Credits. This project extends yunojuno/django-s3-upload with multipart uploads, pause/resume, and related features. Thanks to the original authors and maintainers.
Compatibility
This library supports Python 3.12+ and Django 5.2-6.0.
Allows direct uploading of a file from the browser to AWS S3 via a file input field rendered by Django.
The uploaded file's URL is then saveable as the value of that field in the database.
This avoids the problem of uploads timing out when they go via a web server before being handed off to S3.
Features include:
- displaying a progress bar
- multipart uploads for large files (default threshold 5 MB) with pause and resume
- support for ACLs (eg, private uploads)
- support for encrypted-at-rest S3 buckets
- mimetype and file extension whitelisting
- specifying different bucket destinations on a per-field basis
Installation
Install with Pip:
pip install django-s3-upload-multipart
AWS Setup
Access Credentials
You have two options of providing access to AWS resources:
- Add credentials of an IAM user to your Django settings (see below)
- Use the EC2 instance profile and its attached IAM role
Whether you are using an IAM user or a role, there needs to be an IAM policy in effect that grants permission to upload to S3:
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:PutObjectAcl"],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
If the instance profile is to be used, the IAM role needs to have a Trust Relationship configuration applied:
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
Note that in order to use the EC2 instance profile, django-s3-upload needs to query the EC2 instance
metadata using utility functions from the botocore [] package. You already have botocore
installed if boto3 is a dependency of your project.
S3 CORS
Setup a CORS policy on your S3 bucket.
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>http://yourdomain.com:8080</AllowedOrigin>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Django Setup
settings.py
INSTALLED_APPS = [
...
's3upload',
...
]
TEMPLATES = [{
...
'APP_DIRS': True,
...
}]
# AWS
# If these are not defined, the EC2 instance profile and IAM role are used.
# This requires you to add boto3 (or botocore, which is a dependency of boto3)
# to your project dependencies.
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_STORAGE_BUCKET_NAME = ''
# The region of your bucket, more info:
# http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
S3UPLOAD_REGION = 'us-east-1'
# [Optional] Custom bucket endpoint url, with following keys (also optional):
# region - region of your bucket
# bucket - your bucket name
# S3UPLOAD_BUCKET_ENDPOINT = 'https://{region}.non-amazon-s3-url.com/{bucket}'
# Destinations, with the following keys:
#
# key [required] Where to upload the file to, can be either:
# 1. '/' = Upload to root with the original filename.
# 2. 'some/path' = Upload to some/path with the original filename.
# 3. functionName = Pass a function and create your own path/filename.
# auth [optional] An ACL function to whether the current Django user can perform this action.
# allowed [optional] List of allowed MIME types.
# acl [optional] Give the object another ACL rather than 'public-read'.
# cache_control [optional] Cache control headers, eg 'max-age=2592000'.
# content_disposition [optional] Useful for sending files as attachments.
# bucket [optional] Specify a different bucket for this particular object.
# server_side_encryption [optional] Encryption headers for buckets that require it.
S3UPLOAD_DESTINATIONS = {
'example_destination': {
# REQUIRED
'key': 'uploads/images',
# OPTIONAL
'auth': lambda u: u.is_staff, # Default allow anybody to upload
'allowed_types': ['image/jpeg', 'image/png', 'video/mp4'], # Default allow all mime types
'allowed_extensions': ('.jpg', '.jpeg', '.png'), # Defaults to all extensions
'bucket': 'pdf-bucket', # Default is 'AWS_STORAGE_BUCKET_NAME'
'acl': 'private', # Defaults to 'public-read'
'cache_control': 'max-age=2592000', # Default no cache-control
'content_disposition': 'attachment', # Default no content disposition
'content_length_range': (5000, 20000000), # Default allow any size
'server_side_encryption': 'AES256', # Default no encryption
}
}
# [Optional] Multipart uploads: files larger than this size (default 5 MB) use S3
# multipart upload with pause/resume. Part size must be at least 5 MB per S3 rules.
# S3UPLOAD_MULTIPART_CHUNK_SIZE = 5 * 1024 * 1024
Multipart uploads
For files larger than the chunk size (default 5 MB), the widget uses S3’s multipart upload API instead of a single presigned POST. This avoids timeouts on large files and supports pause and resume in the same browser session.
- When it’s used: Any file larger than
S3UPLOAD_MULTIPART_CHUNK_SIZE(default 5 MB) is uploaded in chunks. Smaller files still use the normal presigned POST flow. - Chunk size: Default is 5 MB (
5 * 1024 * 1024). S3 requires at least 5 MB per part (except the last). SetS3UPLOAD_MULTIPART_CHUNK_SIZEin settings to override. - Pause / Resume: During a multipart upload, the widget shows Pause and Resume. Pausing stops sending new parts; resuming continues from the next part. State is in-memory only (resume is lost on page refresh).
- CORS: Your S3 bucket CORS must allow
PUT(see AWS Setup above) so the browser can upload parts directly to S3. - URLs: Include
s3upload.urlsas usual; multipart uses the same destination and auth asget_upload_params(initiate, sign part, complete, and abort are under the same path prefix).
No extra configuration is required for multipart; the same destinations and permissions apply. To disable multipart and always use presigned POST, set S3UPLOAD_MULTIPART_CHUNK_SIZE to a value larger than your maximum file size.
urls.py
urlpatterns = [
path(r'^s3upload/', include('s3upload.urls')),
]
Run python manage.py collectstatic if required.
Use in Django admin
models.py
from django.db import models
from s3upload.fields import S3UploadField
class Example(models.Model):
video = S3UploadField(dest='example_destination')
Use the widget in a custom form
forms.py
from django import forms
from s3upload.widgets import S3UploadWidget
class S3UploadForm(forms.Form):
images = forms.URLField(widget=S3UploadWidget(dest='example_destination'))
*Optional. You can modify the HTML of the widget by overiding template s3upload/templates/s3upload-widget.tpl
views.py
from django.views.generic import FormView
from .forms import S3UploadForm
class MyView(FormView):
template_name = 'form.html'
form_class = S3UploadForm
templates/form.html
<html>
<head>
<meta charset="utf-8" />
<title>s3upload</title>
{{ form.media }}
</head>
<body>
<form action="" method="post">{% csrf_token %} {{ form.as_p }}</form>
</body>
</html>
Examples
Examples of both approaches can be found in the examples folder. To run them:
$ git clone git@github.com:sahilasopa/django-s3-upload-multipart.git
$ cd django-s3-upload-multipart
# Add your AWS keys to your environment
export AWS_ACCESS_KEY_ID='...'
export AWS_SECRET_ACCESS_KEY='...'
export AWS_STORAGE_BUCKET_NAME='...'
export S3UPLOAD_REGION='...' # e.g. 'eu-west-1'
$ docker-compose up
Visit http://localhost:8000/admin to view the admin widget and http://localhost:8000/form to
view the custom form widget.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_s3_upload_multipart-1.4.0.tar.gz.
File metadata
- Download URL: django_s3_upload_multipart-1.4.0.tar.gz
- Upload date:
- Size: 85.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.13.3 Linux/6.14.0-37-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7858732700ae784176112f5e5cfd7d9f4d87eddfd61bd6d94644914d1a13ac7f
|
|
| MD5 |
1abac20fbba3b02cec3d9a78b1c65ef2
|
|
| BLAKE2b-256 |
f88c2666afc0194f2289c110764802572e5ffb03071742bc67af4a72b61b8178
|
File details
Details for the file django_s3_upload_multipart-1.4.0-py3-none-any.whl.
File metadata
- Download URL: django_s3_upload_multipart-1.4.0-py3-none-any.whl
- Upload date:
- Size: 89.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.3.2 CPython/3.13.3 Linux/6.14.0-37-generic
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df16de49a28ee05fc7f7259978b5d4881778d2b5bdd6a9450bee523d546a5498
|
|
| MD5 |
8a694fd5eeeed0d9c9b048d50079371d
|
|
| BLAKE2b-256 |
8a6ba3b006a8c50c30475fd18f973707af3933e6d4aaa28f8e3cca6865b15eba
|