etianen / django-s3-storage

Django Amazon S3 file storage.
BSD 3-Clause "New" or "Revised" License
414 stars 94 forks source link

S3 files can only be opened in read-only mode #123

Closed zamanehsani closed 2 years ago

zamanehsani commented 3 years ago

I have an image field in django model. before i save the image from the form, i want to resize and crop image and then only to save in s3 bucket. when i was using django-storages, it worked fine. moving to django-s3-storage, gives me the error of

S3 files can only be opened in read-only mode.

this is the code snippet of my resizing and editing in django form:

def save(self):
        photo = super(ProfileUpdateForm, self).save()
        x = self.cleaned_data.get('x')
        y = self.cleaned_data.get('y')
        w = self.cleaned_data.get('width')
        h = self.cleaned_data.get('height')
        image = Image.open(photo.image)
        cropped_image = image.crop((x, y, w+x, h+y))
        resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
        fh = default_storage.open(photo.image.name, 'wb')
        resized_image.save(fh, 'png')
        fh.close()
        return photo

also, if i remove the mode arg of open __(fh = default_storage.open(photo.image.name) )__, it does not edit and crop the image and just upload the original.

also, i tries: to open a PIL image format, but no luck:

        fh = default_storage.open(resized_image, 'wb')
        resized_image.save(fh, 'png')
        fh.close()

finally; i tried to make my s3 bucket publicly accessible and give all permissions. also did not works. I realized that it gotta be django-s3-storages.
i would be supper and more then happy to be advised and or any help as i am stacked at this for more then two days.

etianen commented 3 years ago

AFAIK, the way django-storages does this is a bit of a lie. The file is hosted on S3, which is at the other end of a network connection. Editing that remote file like it's a local file can only be done in a few ways:

  1. Buffer the file locally in memory, and have it re-sync the whole file to S3 on close.
  2. As (1) but buffer to disk.
  3. Somehow emulate a file but every read/write operation results in a network request to S3. This is horribly slow.

I think django-storages does 1 or 2. (1) is best for small files. (2) is best for huge files. Either way, pretending the file is editable is untrue.

You should instead be explicit, and:

  1. Open the file in readonly mode ("r"). This will download the entire file from S3 into a local temporary file (possibly in memory, possibly on disk, automatically chosen depending on size).
  2. Modify the file object as desired. You can use PIL here if you want.
  3. Re-save the file using default_storage.save().

On Tue, 25 May 2021 at 10:31, Zee98 @.***> wrote:

I have an image field in django model. before i save the image from the form, i want to resize and crop image and then only to save in s3 bucket. when i was using django-storages, it worked fine. moving to django-s3-storage, gives me the error of ''S3 files can only be opened in read-only mode'' . this is the code snippet of my resizing and editing in django form:

def save(self):

    photo = super(ProfileUpdateForm, self).save()
    x = self.cleaned_data.get('x')
    y = self.cleaned_data.get('y')
    w = self.cleaned_data.get('width')
    h = self.cleaned_data.get('height')
    image = Image.open(photo.image)
    cropped_image = image.crop((x, y, w+x, h+y))
    resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS)
    fh = default_storage.open(photo.image.name, 'wb')
    resized_image.save(fh, 'png')
    fh.close()
    return photo

also, if i remove the mode arg of open (fh = default_storage.open( photo.image.name) ), it does not edit and crop the image and just upload the original.

also, i tries: to open a PIL image format, but no luck:

    fh = default_storage.open(resized_image, 'wb')
    resized_image.save(fh, 'png')
    fh.close()

finally; i tried to make my s3 bucket publicly accessible and give all permissions. also did not works. I realized that it gotta be django-s3-storages. i would be supper and more then happy to be advised and or any help as i am stacked at this for more then two days.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/etianen/django-s3-storage/issues/123, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABEKCCQPCDD5DXFIMTIKZTTPNU7NANCNFSM45O52CSA .