1

我有一个允许上传图片的 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)
4

3 回答 3

1

经过大量挖掘,我想出了两种不同的解决方案!

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")
于 2019-02-25T14:36:30.763 回答
1

尝试这个:

 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)
于 2019-02-24T21:41:26.273 回答
0

您可以使用一个很好的库来完成您想做的事情。

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

它在上传时制作原始文件的缩略图。它还与 S3 完全兼容。

于 2021-02-18T19:46:15.890 回答