How to generate presigned S3 urls using django-storages?
Asked Answered
M

2

16

I have a Django form which saves a file to s3 through the django-storages library and works fine. How can I generate and return a pre-signed url so the user can access the file temporarily after it is uploaded ? Is this abstracted by django-storages or do I have to use the boto3 api?

I have spent hours going through the Django-storages documentation however it is not very clear how to do this ..

form.py

class DocumentForm(forms.Form):
    docfile = forms.FileField(
        label='Select a file',
        help_text='max. 42 megabytes'
    )
   name = models.CharField(max_length=20)
   uploaded_at = models.DateTimeField(auto_now_add=True)

views.py

def upload_file(request):
   if request.method == 'POST':
      form = DocumentForm(request.POST)
      if form.is_valid():
         form.save()
         url = ... # generate pre-signed url of uploaded file here
         return render(request, 'upload_response.html', url)

Masson answered 4/10, 2020 at 9:49 Comment(1)
also see aws boto3 docs for pre-signed urlsRacial
M
17

Turns out you do not need to use boto3 to generate a presigned url. Django-storages abstracts the entire process. You can simply access the url attribute on the FileField, like in this example:

document_form = DocumentForm.objects.get(pk=1)
url = document_form.docfile.url

--- Edit ----

For reference, here is the S3 storage class method that generates the pre-signed url for you https://github.com/jschneier/django-storages/blob/770332b598712da27ecdba75c9e202ad6a1a8722/storages/backends/s3boto3.py#L554

Masson answered 18/2, 2021 at 16:30 Comment(4)
Can we get a reference to source on this?Condenser
I have just edited the answer with a link to the referenceMasson
To actually return a URL with signature, make sure AWS_QUERYSTRING_AUTH = True.Glenglencoe
Good point. I believe it is set to True by default if not explicitly set in settings.pyMasson
A
3

Here is sample code for generating pre-signed url for object in S3

import boto3

client = boto3.client('s3')
response = client.generate_presigned_url('get_object',Params={'Bucket': bucket_name,
                                                              'Key': objectpath},
                                         HttpMethod="GET", ExpiresIn=expires_in)
Aruba answered 9/10, 2020 at 16:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.