简体   繁体   English

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

[英]Python/Django download Image from URL, modify, and save to ImageField

I've been looking for a way to download an image from a URL, preform some image manipulations (resize) actions on it, and then save it to a django ImageField. 我一直在寻找一种从URL下载图像,在其上执行一些图像处理(调整大小)动作,然后将其保存到django ImageField的方法。 Using the two great posts (linked below), I have been able to download and save an image to an ImageField. 使用两个很棒的帖子(下面链接),我已经能够下载图像并将其保存到ImageField。 However, I've been having some trouble manipulating the file once I have it. 但是,一旦我拥有它,我一直在操作文件时遇到一些麻烦。

Specifically, the model field save() method requires a File() object as the second parameter. 具体来说,模型字段save()方法需要File()对象作为第二个参数。 So my data has to eventually be a File() object. 所以我的数据最终必须是一个File()对象。 The blog posts linked below show how to use urllib2 to save your an image URL into a File() object. 下面链接的博客文章显示了如何使用urllib2将图像URL保存到File()对象中。 This is great, however, I also want to manipulate the image using PIL as an Image() object. 这很好,但是,我还想使用PIL作为Image()对象来操作图像。 (or ImageFile object). (或ImageFile对象)。

My preferred approach would be then to load the image URL directly into an Image() object, preform the resize, and convert it to a File() object and then save it in the model. 我首选的方法是将图像URL直接加载到Image()对象中,预先形成resize,然后将其转换为File()对象,然后将其保存在模型中。 However, my attempts to convert an Image() to a File() have failed. 但是,我将Image()转换为File()的尝试失败了。 If at all possible, I want to limit the number of times I write to the disk, so I'd like to do this object transformation in Memory or using a NamedTemporaryFile(delete=True) object so I don't have to worry about extra files laying around. 如果可能的话,我想限制我写入磁盘的次数,所以我想在内存中使用这个对象转换或使用NamedTemporaryFile(delete = True)对象,所以我不必担心周围的额外文件。 (Of course, I want the file to be written to disk once it is saved via the model). (当然,我希望通过模型保存文件后将文件写入磁盘)。

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,
         )

With this approach, the file appears corrupt whenever I view it as an image. 使用此方法,每当我将其视为图像时,该文件都会显示为损坏。 Does anyone have any approach that takes a file file from a URL, allows one to manipulate it as an Image and then save it to a Django ImageField? 有没有人有任何从URL获取文件文件的方法,允许人们将其作为图像操作,然后将其保存到Django ImageField?

Any help is much appreciated. 任何帮助深表感谢。

Programmatically saving image to Django ImageField 以编程方式将图像保存到Django ImageField

Django: add image in an ImageField from image url Django:从图像url在ImageField中添加图像

Update 08/11/2010: I did end up going with StringIO, however, I was stringIO was throwing an unusual Exception when I tried to save it in a Django ImageField. 更新08/11/2010:我最终使用StringIO,但是,当我尝试将其保存在Django ImageField中时,我发现了一个异常的异常。 Specifically, the stack trace showed a name error: 具体来说,堆栈跟踪显示名称错误:

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

After digging through the Django source, it looks like this error was caused when the model save tries to access the size attribute of the StringIO "File". 在挖掘Django源代码之后,当模型保存尝试访问StringIO“File”的size属性时,看起来会出现此错误。 (Though the error above indicates a problem with the name, the root cause of this error appears to be the lack of a size property on the StringIO image). (虽然上面的错误表明名称有问题,但此错误的根本原因似乎是StringIO图像上缺少size属性)。 As soon as I assigned a value to the size attribute of the image file, it worked fine. 只要我为图像文件的size属性赋值,它就可以正常工作。

In an attempt to kill 2 birds with 1 stone. 试图用1块石头杀死2只鸟。 Why not use a (c)StringIO object instead of a NamedTemporaryFile? 为什么不使用(c)StringIO对象而不是NamedTemporaryFile? You won't have to store it on disk anymore and I know for a fact that something like this works (I use similar code myself). 你不必将它存储在磁盘上了,我知道这样的事情是有用的(我自己使用类似的代码)。

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

file_object = File(img_temp, filename)

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

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