Kakar
Kakar

Reputation: 5609

How to get the aws s3 object key using django-storages and boto3

I am using django-storage and boto3 for media and static files using aws s3. I need to get the object key of aws s3 bucket, so that I can generate a url for that object.

client = boto3.client('s3')
bucket_name = 'django-bucket'

key = ???

u = client.generate_presigned_url('get_object', Params = {'Bucket': bucket_name, 'Key': key,'ResponseContentType':'image/jpeg', 'ResponseContentDisposition': 'attachment; filename="your-filename.jpeg"'}, ExpiresIn = 1000)

These are in my settings:

STATICFILES_LOCATION = 'static'
MEDIAFILES_LOCATION = 'media'
STATICFILES_STORAGE = 'myproject.custom_storages.StaticStorage'
DEFAULT_FILE_STORAGE = 'myproject.custom_storages.MediaStorage'
AWS_ACCESS_KEY_ID = "my_access_key_id"
AWS_SECRET_ACCESS_KEY = "my_secret_access_key"
AWS_STORAGE_BUCKET_NAME = "django-bucket"
AWS_QUERYSTRING_AUTH = False
AWS_S3_CUSTOM_DOMAIN = AWS_STORAGE_BUCKET_NAME + ".s3.amazonaws.com"
# static media settings
STATIC_URL = "https://" + AWS_STORAGE_BUCKET_NAME + ".s3.amazonaws.com/"
MEDIA_URL = STATIC_URL + "media/"
ADMIN_MEDIA_PREFIX = STATIC_URL + "admin/"

I can get the file path of the image file

ui = UserImage.objects.get(user=user_id, image=image_id)
url = ui.image.url

'https://django-bucket.s3.amazonaws.com/media/user_image/1497598249_49.jpeg'

But I don't know how to get the s3 object key so that I can generate a url for that object.

Upvotes: 4

Views: 4196

Answers (2)

Alik
Alik

Reputation: 41

You can get s3 Object key by:

ui = UserImage.objects.get(user=user_id, image=image_id)
bucket_key = ui.image.file.obj.key

'media/user_image/1497598249_49.jpeg'

Upvotes: 3

user1936977
user1936977

Reputation: 151

It would seem the prefix can be constructed from the file field 'storage' location value and the file 'name' (which is a path from the 'location' to the file - it includes what most of us think of as the file 'name').

Here's a quick demo of a function that should get the job done:

import os

def get_file_key(file_field):
    return os.path.join(file_field.storage.location, file_field.name)

Use as follows:

prefix = get_file_key(my_model_instance.relevant_file_field)

Notes:

You'll probably want to implement error catching sanity checking in/around the function as appropriate for your needs - for example the function will raise an AttributeError if the file_field is None - and in most scenarios you almost certainly wouldn't want to end up with just the location if for some reason the field.name returned an empty string as a result of a bug or just because that was saved somehow (or '/' if the location wasn't set)

Upvotes: 5

Related Questions