Как сохранить эскиз в default_storage(AWS S3) после преобразования его в Django views.py?

У меня есть HTML-форма, которая позволяет загружать изображения. Я хочу сохранить исходное изображение в хранилище S3, а затем преобразовать его в миниатюру и сохранить миниатюру в том же хранилище.

Я мог сохранить только исходное изображение, но после преобразования его в миниатюру с помощью PIL при попытке сохранить его я получил "Ошибка сервера 500"

Мой код просмотра выглядит следующим образом:

from django.core.files.storage import default_storage as storage
class upload(View):
def post(self, request):
    image = request.FILES['pic']
    storage.save(image.name, image)
    thisfile = storage.open(image.name)
    newimg = Image.open(thisfile)
    thumb = newimg.resize((128,128), Image.ANTIALIAS)
    storage.save("newimagename", newimg)

    #Trying to save it this way doesn't work either
    #thisobj = userProfile.objects.get(user= request.user)
    #thisobj.image = newimg
    #thisobj.save()

Я попробовал некоторые операторы печати, чтобы убедиться, что он без проблем конвертирует файл, но он сохранил его в памяти и печатает как

<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=600x600 at 0x105C1DEF0>

Я попытался переписать метод сохранения в models.py, но я получаю ту же ошибку

def save(self, *args, **kwargs):
    super(userProfile, self).save(*args, **kwargs)
    if self.image:
        self.image.name = "y.JPG"
        image = Image.open(self.image.path)
        image = image.resize((128,128), Image.ANTIALIAS)
        image.save(self.image.path)

3 ответа

Попробуй это:

 def save(self, *args, **kwargs):
     super().save(*args, **kwargs)
     img = Image.open(self.image.path)
     if img.height > 128 or img.width > 128:
         output_size = (128, 128)
         img.thumbnail(output_size)
         img.save(self.image.path)

После долгих раскопок я нашел 2 разных решения!

1- Переопределение метода "Сохранить" в models.py следующим образом:

from PIL import Image
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
    def save(self, *args, **kwargs):
    super(userProfile, self).save(*args, **kwargs)
    previous = userProfile.objects.get(id = self.id)
    if self.image.width > 128:
        orig = Image.open(self.image)
        orig.thumbnail((128,128), Image.ANTIALIAS)
        fileBytes = BytesIO()
        orig.save(fileBytes, format="JPEG")
        memoryFile = InMemoryUploadedFile(fileBytes, None, str(self.user) + "_thumb.JPG", 'image/jpeg',1, None)
        self.image = memoryFile
        self.image.save(self.image.name, self.image)

2. Сохраните загруженный файл, используя хранилище по умолчанию.

from io import BytesIO
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import InMemoryUploadedFile
class upload(View):
  def post(self, request):
    image = request.FILES['pic']
    #Save the image first to the DB
    default_storage.save(image.name, image)
    #Open the file in the DB
    thisdude = default_storage.open(image.name)
    #Use the opened file in the DB in Images
    img = Image.open(thisdude)
    # Resize that babe
    img.thumbnail((128, 128), Image.ANTIALIAS)
    #Get the Bytes of the file from memory
    thumbnailString = BytesIO()
    #Save the image with the bytes as JPEG
    img.save(thumbnailString, format='JPEG')
    #Get the file in the memory
    thumb_file = InMemoryUploadedFile(thumbnailString, None, 'foo.jpg', 'image/jpeg',1, None)
    #Save it to the DB
    default_storage.save("abc.jpg", thumb_file)
    return redirect("index")

Вы могли бы использовать хорошую библиотеку, которая делает именно то, что вы хотели.

https://github.com/codingjoe/django-stdimage

Он создает эскизы исходного файла при загрузке. Также он полностью совместим с S3.

Другие вопросы по тегам