在上传到Amazon S3期间,Python Django创建图像缩略图 [英] Python Django Create Image Thumbnail During Upload to Amazon S3

查看:121
本文介绍了在上传到Amazon S3期间,Python Django创建图像缩略图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个功能齐全的Django Web表单,它将在Amazon S3上上传和存储图像.

I have a fully functional Django web form that will upload and store images on Amazon S3.

我还如何为正在上传的同一图像创建其他尺寸调整后的副本,并将它们同时上传到Amazon S3?

How can I also create an additional re-sized copies of the same image that is being uploaded and upload them at the same time to Amazon S3?

理想情况下,我将有两个其他尺寸(120x90、240x180)保存到S3上的/small//medium/文件夹中.

Ideally, I will have two additional sizes (120x90, 240x180) saved to /small/ and /medium/ folders on S3.

对于上传到S3,我使用的是django-storagesboto.

For the upload to S3, I'm using django-storages and boto.

我环顾四周并尝试了不同的方法,但是似乎所有产生拇指的代码都在处理本地存储的文件或已在线存储在某处的图像.

I have looked around and tried different ways, but it seems that all the thumb generating codes floating around are dealing with locally stored files or images that are already stored somewhere online.

我的代码:

models.py

def content_file_name(instance, filename):
    ext = filename.split('.')[-1]
    name = uuid.uuid4().hex
    filename = "%s_%s.%s" % (instance.business_id, name, ext)
    path = 'originals'
    return os.path.join(path, filename)

class Photo(models.Model):
    filename = models.ImageField(upload_to=content_file_name)
    phototitle = models.CharField(max_length=50, null=True)
    class Meta:
        db_table = 'photo'

views.py

def create(request):

if request.method == 'POST':
    form = UploadForm(request.POST, request.FILES)

    if form.is_valid():
        form.save()

        return ...
else:
    form = UploadForm()

return render(request, 'upload.html', {
    'form': form,
})

form.py

class UplaodForm(ModelForm):

class Meta:
    model = Photo
    fields = "__all__" 

settings.py

AWS_STORAGE_BUCKET_NAME = '...'
AWS_ACCESS_KEY_ID = '...'
AWS_SECRET_ACCESS_KEY = '...'
...

INSTALLED_APPS = (
...
'storages',

推荐答案

我的解决方案适用于任何存储,但是我通过django-storage和boto3在AWS上对其进行了测试.我创建了一个名为ThumbnailStorage的存储,它继承了默认存储(无论它是什么),并在_save方法中添加了缩略图的创建,因此我有了名称和内容.最后,我将此ThumbnailStorage声明为该字段的默认存储空间:

My solution works with any storage, but I tested it for AWS via django-storage and boto3. I created a Storage named ThumbnailStorage inheriting from the default one (whatever it is) and added the creation of the thumbnails in method _save, so that I have the name and the content. As a last step I declared this ThumbnailStorage as the default Storage for the field:

存储空间

from django.core.files.storage import get_storage_class
from PIL import Image


default_storage = get_storage_class()


class ThumbnailStorage(default_storage):

    def _save(self, name, content):

        if hasattr(content, 'content_type'):
            if content.content_type.startswith('image/'):
                self.generate_thumbnails(name, content)
        return super()._save(name, content)

    def generate_thumbnails(self, name, content):

        name1, ext1 = os.path.splitext(name)
        fname, ext = os.path.splitext(content.name)
        format = (ext1 if ext1 != '.jpg' else '.jpeg').strip('.')  

        im = Image.open(content)
        w, h = im.size
        im.thumbnail((120, 90))    # <<< choose your dims
        dest_filename = f'/small/{name}'   # set your name
        fh = default_storage().open(dest_filename, 'wb')
        sfile = io.BytesIO()
        im.save(sfile, format=format)
        fh.write(sfile.getvalue())
        fh.close()

模型

class Photo(models.Model):
    filename = models.ImageField(
        upload_to=content_file_name,
        storage=TumbnailStorage()       # <<< this is where the work is done
    )
    ...

请注意,Pillow不接受jpg,因此您需要将其转换为jpeg,并且当格式为jpeg时(当它适用于png时)我无法im.save(fh),因此我必须添加io.StringIO 技巧

Note that jpg is not accepted by Pillow, so you need to translate to jpeg and that I was not able to im.save(fh) when the format is jpeg (while it works on png) so I had to add io.StringIO trick

这篇关于在上传到Amazon S3期间,Python Django创建图像缩略图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆