【问题标题】:Python Django Create Image Thumbnail During Upload to Amazon S3Python Django 在上传到 Amazon S3 期间创建图像缩略图
【发布时间】:2015-07-18 04:25:12
【问题描述】:

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

我如何还可以为正在上传的同一图像创建一个额外的调整大小的副本,并将它们同时上传到 Amazon S3?

理想情况下,我将另外两个尺寸(120x90、240x180)保存到 S3 上的 /small//medium/ 文件夹。

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

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

我的代码:

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',

【问题讨论】:

标签: python django amazon-web-services amazon-s3


【解决方案1】:

我的解决方案适用于任何存储,但我通过 django-storage 和 boto3 对 AWS 进行了测试。我创建了一个名为ThumbnailStorage 的存储,继承自默认存储(不管它是什么),并在_save 方法中添加了缩略图的创建,这样我就有了名称和内容。作为最后一步,我将 ThumbnailStorage 声明为该字段的默认存储:

存储

import os
import io
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 时我无法 im.save(fh)(而它适用于 png)所以我不得不添加 io.StringIO @ 987654321@

【讨论】:

    猜你喜欢
    • 2015-01-05
    • 2016-07-02
    • 2015-12-20
    • 2012-09-21
    • 2017-03-19
    • 2011-08-18
    • 2019-12-02
    • 2015-12-18
    • 2017-07-18
    相关资源
    最近更新 更多