Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saving another file with same name using django-storage and boto

I have a model Profile and an ImageField associated with it.

The images are uploaded to AWS S3 bucket for storage using django-storages and boto.

If I upload an image with a file name that already exists(eg: sample.png) Django by default would save the new file as sample_1.png which is not working while uploading an image to AWS S3. Is there a way to solve this issue?

How do I upload an image with an already existing file name to AWS S3 without overwriting it?

like image 208
Gowtham Avatar asked Apr 12 '16 16:04

Gowtham


1 Answers

Given you've defined your bucket location in settings.MYMODEL_FILES_LOCATION you can use the following to rename the uploaded files in an arbitrary location, possible derived from the original file name. Following snippet would save the files in /mymodelfiles/.. The model instance properties can be accessed from the instance object in the renaming method, so you can e.g. upload files from the same user under the same subdirectory.

import uuid
import os
from django.utils.deconstruct import deconstructible
from storages.backends.s3boto import S3BotoStorage
from django.db import models
from django.conf import settings


def path_and_rename(prefix, filename):
    ext = filename.split('.')[-1]
    filename = '{}.{}'.format(uuid.uuid4().hex, ext)
    return os.path.join(prefix, filename)


def get_path_for_my_model_file(instance, filename):
    return path_and_rename('mymodelfiles/', filename)


@deconstructible
class MyS3BotoStorage(S3BotoStorage):
    pass


class MyModel(models.Model):
    resources = models.FileField(
        upload_to=get_path_for_my_model_file,
        storage=MyS3BotoStorage(bucket=settings.MYMODEL_FILES_LOCATION))

Constructor of S3BotoStorage can take keyword argument "acl" to set permissions for the uploaded file, e.g. acl='private'

like image 103
hhamalai Avatar answered Nov 03 '22 09:11

hhamalai