I have a fully functional Django web form that will upload and store images on Amazon S3.
我有一个功能齐全的Django Web表单,可以在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?
如何创建正在上传的同一图像的其他重新调整大小的副本,并将它们同时上载到Amazon S3?
Ideally, I will have two additional sizes (120x90, 240x180) saved to /small/
and /medium/
folders on S3.
理想情况下,我将在S3上将两个额外的大小(120x90,240x180)保存到/ small /和/ medium /文件夹。
For the upload to S3, I'm using django-storages
and boto
.
对于上传到S3,我正在使用django-storages和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.
我环顾四周并尝试了不同的方法,但似乎浮动的所有拇指生成代码都处理本地存储的文件或已存储在网上某处的图像。
My Code:
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',
1 个解决方案
#1
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:
我的解决方案适用于任何存储,但我通过django-storage和boto3对AWS进行了测试。我创建了一个名为ThumbnailStorage的存储继承自默认存储(无论它是什么),并在方法_save中添加了缩略图的创建,以便我有名称和内容。作为最后一步,我将此ThumbnailStorage声明为该字段的默认存储:
the storage
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()
the model
class Photo(models.Model):
filename = models.ImageField(
upload_to=content_file_name,
storage=TumbnailStorage() # <<< this is where the work is done
)
...
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
请注意,枕头不接受jpg,所以你需要转换为jpeg并且当格式为jpeg时我无法im.save(fh)(当它在png上工作时)所以我不得不添加io.StringIO技巧
#1
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:
我的解决方案适用于任何存储,但我通过django-storage和boto3对AWS进行了测试。我创建了一个名为ThumbnailStorage的存储继承自默认存储(无论它是什么),并在方法_save中添加了缩略图的创建,以便我有名称和内容。作为最后一步,我将此ThumbnailStorage声明为该字段的默认存储:
the storage
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()
the model
class Photo(models.Model):
filename = models.ImageField(
upload_to=content_file_name,
storage=TumbnailStorage() # <<< this is where the work is done
)
...
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
请注意,枕头不接受jpg,所以你需要转换为jpeg并且当格式为jpeg时我无法im.save(fh)(当它在png上工作时)所以我不得不添加io.StringIO技巧