繁体   English   中英

在将图像添加到存储位置之前,如何在Django中优化图像(文件上传)?

[英]How to optimize an image (file upload) in Django before it is added to the storage location?

我们正在将Django项目的后端存储从本地磁盘存储更新为Amazon S3存储桶。 当前,我们添加图像,然后对其进行优化,然后将其重新同步到我们的CDN。 我们控制了这些步骤,因此我只在上传之后和rsync之前进行优化。

我们正在迁移到Amazon S3,我现在想在将图像上传到S3存储桶之前对其进行优化,主要是为了避免先将图像上传到S3,然后再进行下载以进行优化,最后重新上传。 为什么我们可以合而为一地进行三趟旅行。

我的问题是:在将文件推送到存储后端(在本例中为Amazon S3)之前,我们如何拦截上传以优化文件。

如果有帮助,我正在使用亚马逊的boto库和django-storages-redux。


我有一个草稿形式的问题,意识到我从未张贴过。 我没有在堆栈溢出时找到解决方案,所以我想将其添加为“问答”帖子。

解决方案是重写Django的TemporaryFileUploadHandler类。 我也将上传文件的大小设置为零,因此它们全部都发生在磁盘上,而不发生在内存中,尽管可能没有必要。

      # encoding: utf-8
      from image_diet import squeeze
      import shutil
      import uuid

      from django.core.files import File
      from django.core.files.uploadhandler import TemporaryFileUploadHandler


      class CompressImageUploadHandler(TemporaryFileUploadHandler):
      """
      Run image squeeze on our temporary file before upload to S3
      """

        def __init__(self, *args, **kwargs):
            self.image_types = ('image/jpeg', 'image/png')
            self.file_limit = 200000
            self.overlay_fields = (
                'attribute_name',  
            )
            self.skip_compress_fields = (
                'attribute_name',  
            )
            super(CompressImageUploadHandler, self).__init__(*args, **kwargs)

        def compress_image(self):
            """
            For image files we need to compress them, but we need to do some
            trickery along the way. We need to close the file, pass it to
            image_diet.squeeze, then reopen the file with the same file name
            """

            # if it's an image and small enough. Squeeze.
            if (self.file.size < self.file_limit and
                    self.field_name not in self.skip_compress_fields):
                # the beginning is a good place to start.
                self.file.seek(0)
                # let's squeeze this image. 
                # first, make a copy.
                file_name = self.file.name
                file_content_type = self.file.content_type
                copy_path = u"{}{}".format(
                    self.file.temporary_file_path(),
                    str(uuid.uuid4())[:8]
                )
                shutil.copyfile(
                    self.file.temporary_file_path(),
                    copy_path
                )
                # closed please. image_squeeze updates on an open file
                self.file.close()
                squeeze(copy_path)
                squeezed_file = open(copy_path)
                self.file = File(squeezed_file)
                # now reset some of the original values
                self.file.name = file_name
                self.file.content_type = file_content_type

        def screenshot_overlay(self):
            """
            Apply the guarantee_image_overlay method on screenshots
            """
            if self.field_name in self.overlay_fields:
                # this is a custom method that adds an overlay to the upload image if it's in the tuple of overlay_fields
                guarantee_image_overlay(self.file.temporary_file_path())
                # we have manipulated file, back to zero
                self.file.seek(0)

        def file_complete(self, file_size):
            """
            Return the file object, just run image_squeeze against it.
            This happens before the file object is uploaded to Amazon S3.
            While the pre_save hook happens after the Amazon upload.
            """
            self.file.seek(0)
            self.file.size = file_size

            if self.content_type in self.image_types:
                # see if we apply the screenshot overlay.
                self.screenshot_overlay()
                self.compress_image()

            return super(CompressImageUploadHandler, self).file_complete(file_size)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM