Как сохранить эскиз в 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.