Python / Django从URL下载图像,进行修改并保存到ImageField

发布于 2021-01-29 15:06:15

我一直在寻找一种从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中?

任何帮助深表感谢。

以编程方式将图像保存到Django
ImageField

Django:通过图片网址在ImageField中添加图片

2010年8月11日更新:我最终使用了StringIO,但是,当我试图将其保存在Django
ImageField中时,stringIO抛出了一个异常异常。具体来说,堆栈跟踪显示了名称错误:

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

深入研究Django源代码之后,当模型保存尝试访问StringIO“
File”的size属性时,似乎导致了此错误。(尽管上面的错误表明名称有问题,但此错误的根本原因似乎是StringIO映像上缺少size属性)。一旦为图像文件的size属性分配了一个值,它就可以正常工作。

关注者
0
被浏览
52
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    企图用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)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看