【问题标题】:Django - Getting PIL Image save method to work with Amazon s3boto StorageDjango - 获取 PIL 图像保存方法以使用 Amazon s3boto 存储
【发布时间】:2013-01-18 18:34:15
【问题描述】:

为了在上传时调整图像大小(使用 PIL),我将覆盖我的文章模型的保存方法,如下所示:

def save(self):
    super(Article, self).save()
    if self.image:
        size = (160, 160)
        image = Image.open(self.image)
        image.thumbnail(size, Image.ANTIALIAS) 
        image.save(self.image.path)

这在本地有效,但在生产中出现错误: NotImplementedError: 此后端不支持绝对路径。

我尝试用

替换 image.save 行
image.save(self.image.url)

然后我得到一个 IOError: [Errno 2] 没有这样的文件或目录:'https://my_bucket_name.s3.amazonaws.com/article/article_images/2.jpg'

不过,这是图像的正确位置。如果我将该地址放在浏览器中,图像就在那里。我尝试了许多其他方法,但到目前为止,没有运气。

【问题讨论】:

  • 这是您第一次在本地机器之外的其他地方运行您的网站吗?

标签: django amazon-s3 python-imaging-library boto


【解决方案1】:

你应该尽量避免保存到绝对路径;有一个 File Storage API 为您抽象了这些类型的操作。

查看PIL Documentation,似乎save() 函数支持传递类似文件的对象而不是路径。

我不在可以测试此代码的环境中,但我相信您需要做这样的事情而不是最后一行:

from django.core.files.storage import default_storage as storage

fh = storage.open(self.image.name, "w")
format = 'png'  # You need to set the correct image format here
image.save(fh, format)
fh.close()

【讨论】:

  • 试过了。得到一个 AttributeError:'NoneType' 对象没有属性 'write'。似乎 fh = None
  • 我通过更改第一行使其工作。我试图编辑您的答案,以便在编辑被批准后接受它,但编辑被拒绝。不知道为什么。这是我添加/更改以使其正常工作的内容: from django.core.files.storage import default_storage as storage fh = storage.open(self.image.name, "w")
  • 我正在实现完全相同的东西,但它说 _getencoder 方法中存在错误。它需要 11 个参数,但我给它 13 个。
  • 我在这里创建了损坏的图像,直到我将"w" 更改为"wb"(明确指定它是一个二进制文件)。不过,不确定需要进行此更改的条件是什么。
【解决方案2】:

对我来说 default.storage.write() 不起作用,image.save() 不起作用,这个起作用了。如果有人仍然感兴趣,请参阅此代码。我为缩进道歉。我的项目是使用 Cloudinary 和 Django 的小项目。

    from io import BytesIO
    from django.core.files.base import ContentFile
    from django.core.files.storage import default_storage as storage    

    def save(self, *args, **kargs):
    super(User, self).save(*args, **kargs)
    # After save, read the file
    image_read = storage.open(self.profile_image.name, "r")
    image = Image.open(image_read)
        if image.height > 200 or image.width > 200:
           size = 200, 200
        
          # Create a buffer to hold the bytes
           imageBuffer = BytesIO()

          # Resize  
           image.thumbnail(size, Image.ANTIALIAS)

          # Save the image as jpeg to the buffer
           image.save(imageBuffer, image.format)

          # Check whether it is resized
           image.show()

          # Save the modified image
           user = User.objects.get(pk=self.pk)
           user.profile_image.save(self.profile_image.name, ContentFile(imageBuffer.getvalue()))

           image_read = storage.open(user.profile_image.name, "r")
           image = Image.open(image_read)
           image.show()

        image_read.close()

【讨论】:

    【解决方案3】:

    如果您使用 云存储 存储 Django 中的文件

    NotImplementedError: This backend doesn't support absolute paths

    要修复它,您需要将 file.path 替换为 file.name

    对于问题中的代码:image.save(self.image.path)image.save(self.image.name)

    这是控制台中的样子

    >>> c = ContactImport.objects.last()
    
    >>> c.json_file.name
    'protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json'
    
    >>> c.json_file
    <FieldFile: protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json>
    
    >>> c.json_file.url
    'https://storage.googleapis.com/super-secret/media/api/protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json?Expires=1631378947&GoogleAccessId=secret&Signature=ga7...'
    
    

    【讨论】:

      猜你喜欢
      • 2013-11-08
      • 2016-04-22
      • 1970-01-01
      • 2012-08-02
      • 2014-12-27
      • 2022-01-14
      • 2019-12-17
      • 2013-01-05
      • 2018-11-21
      相关资源
      最近更新 更多