[英]Django: Image Resize and Upload with PIL, Amazon S3 and Boto
[英]Python Django Create Image Thumbnail During Upload to Amazon S3
我有一个功能齐全的Django Web表单,它将在Amazon S3上上传和存储图像。
我还如何为正在上传的同一图像创建其他尺寸调整后的副本,并将它们同时上传到Amazon S3?
理想情况下,我将在S3上的/small/
和/medium/
文件夹中保存了两个其他尺寸(120x90、240x180)。
为了上传到S3,我使用django-storages
和boto
。
我环顾四周并尝试了不同的方法,但似乎所有产生拇指的代码都在处理本地存储的文件或已在线存储在某处的图像。
我的代码:
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,
})
表格
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
声明为该字段的默认存储:
储存空间
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 技巧
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.