【问题标题】:Python/Django download Image from URL, modify, and save to ImageFieldPython/Django 从 URL 下载图片,修改,保存到 ImageField
【发布时间】:2011-03-27 14:40:05
【问题描述】:

我一直在寻找一种从 URL 下载图像的方法,对其执行一些图像操作(调整大小)操作,然后将其保存到 django ImageField。使用这两个很棒的帖子(链接如下),我已经能够下载图像并将其保存到 ImageField。但是,一旦我拥有该文件,我在操作该文件时遇到了一些麻烦。

具体来说,模型字段 save() 方法需要一个 File() 对象作为第二个参数。所以我的数据最终必须是一个 File() 对象。下面链接的博客文章展示了如何使用 urllib2 将图像 URL 保存到 File() 对象中。这很好,但是,我还想使用 PIL 作为 Image() 对象来操作图像。 (或 ImageFile 对象)。

我的首选方法是将图像 URL 直接加载到 Image() 对象中,执行调整大小,并将其转换为 File() 对象,然后将其保存在模型中。但是,我尝试将 Image() 转换为 File() 失败了。如果可能的话,我想限制写入磁盘的次数,所以我想在内存中进行这个对象转换或使用 NamedTemporaryFile(delete=True) 对象,所以我不必担心额外的文件。 (当然,我希望文件通过模型保存后写入磁盘)。

import urllib2
from PIL import Image, ImageFile    
from django.core.files import File
from django.core.files.temp import NamedTemporaryFile

inStream = urllib2.urlopen('http://www.google.com/intl/en_ALL/images/srpr/logo1w.png')

parser = ImageFile.Parser()
while True:
    s = inStream.read(1024)
    if not s:
        break
    parser.feed(s)

inImage = parser.close()
# convert to RGB to avoid error with png and tiffs
if inImage.mode != "RGB":
    inImage = inImage.convert("RGB")

# resize could occur here

# START OF CODE THAT DOES NOT SEEM TO WORK
# I need to somehow convert an image .....

img_temp = NamedTemporaryFile(delete=True)
img_temp.write(inImage.tostring())
img_temp.flush()

file_object = File(img_temp)

# .... into a file that the Django object will accept. 
# END OF CODE THAT DOES NOT SEEM TO WORK

my_model_instance.image.save(
         'some_filename',
         file_object,  # this must be a File() object
         save=True,
         )

使用这种方法,每当我将文件作为图像查看时,它就会出现损坏。有没有人有任何方法可以从 URL 获取文件文件,允许将其作为图像进行操作,然后将其保存到 Django ImageField?

非常感谢任何帮助。

Programmatically saving image to Django ImageField

Django: add image in an ImageField from image url

2010 年 8 月 11 日更新:我确实最终选择了 StringIO,但是,当我尝试将 stringIO 保存在 Django ImageField 中时,它抛出了一个不寻常的异常。具体来说,堆栈跟踪显示名称错误:

"AttribueError exception "StringIO instance has no attribute 'name'"

在挖掘 Django 源代码后,看起来这个错误是由于模型保存尝试访问 StringIO“文件”的 size 属性引起的。 (虽然上面的错误表明名称有问题,但此错误的根本原因似乎是 StringIO 图像上缺少 size 属性)。一旦我为图像文件的大小属性分配了一个值,它就可以正常工作。

【问题讨论】:

  • 我还使用 StringIO 将图像保存到内存中,然后使用 File.open() 读取它,但也遇到了一些问题。

标签: python django file python-imaging-library urllib2


【解决方案1】:

试图用 1 块石头杀死 2 只鸟。为什么不使用 (c)StringIO 对象而不是 NamedTemporaryFile?您不必再将它存储在磁盘上,而且我知道这样的事情确实有效(我自己使用类似的代码)。

from cStringIO import StringIO
img_temp = StringIO()
inImage.save(img_temp, 'PNG')
img_temp.seek(0)

file_object = File(img_temp, filename)

【讨论】:

  • 感谢 WoLpH,感谢您的帮助。我尝试了您的解决方案,但仍然遇到一些问题。具体来说,当我最后调用 save() 时,我得到 AttribueError 异常 "StringIO instance has no attribute 'name'" ------------------ img_temp = StringIO.StringIO (); inImage.save(img_temp, format='PNG'); img_temp.seek(0);
  • @Joe J:当使用StringIO 时,filename 参数是强制性的。这就是你现在的问题;)
  • 再次感谢 WoLpH。文件名是否必须与文件系统上的路径相对应,还是只是临时文件的一些随机组成的名称?
  • @Joe J:只要使用随机文件名,或者如果可用的话,使用原始文件名。不需要路径,只需一个文件名。
  • inImage.save 应该用img_temp 作为参数而不是fh 来调用,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多