2010-08-10 75 views
10

我一直在尋找一種方式來從URL下載圖像,對其執行一些圖像操作(調整大小)操作,然後將其保存到django ImageField。使用這兩個偉大的文章(下面鏈接),我已經能夠下載並保存圖像到一個ImageField。但是,一旦擁有它,我一直在操作文件時遇到一些麻煩。Python/Django下載從URL的圖像,修改,並保存到ImageField

具體來說,模型字段save()方法需要File()對象作爲第二個參數。所以我的數據最終必須是一個File()對象。下面鏈接的博客文章展示瞭如何使用urllib2將您的圖片URL保存到File()對象中。然而,這非常棒,我也想使用PIL作爲Image()對象來操作圖像。 (或ImageFile對象)。

我的首選方法是直接將圖像URL加載到Image()對象中,執行調整大小,然後將其轉換爲File()對象,然後將其保存在模型中。但是,我嘗試將Image()轉換爲File()失敗。如果可能的話,我想限制寫入磁盤的次數,所以我想在Memory中做這個對象轉換或者使用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

更新08/11/2010:我沒有最終用StringIO去,不過,我是StringIO的被扔一個不尋常的例外,當我試圖將其保存在一個Django的ImageField。具體來說,堆棧跟蹤顯示的名稱錯誤:

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

通過Django的源挖掘後,它看起來像這樣的錯誤是當模型保存嘗試訪問StringIO的「文件」的大小屬性造成的。 (儘管上面的錯誤表明名稱存在問題,但此錯誤的根本原因似乎是StringIO映像中缺少大小屬性)。只要我給圖像文件的size屬性賦值,它就可以正常工作。

+0

我也用StringIO將圖像保存到內存,然後用File.open()讀取它,但也有一些問題。 – 2010-08-10 02:26:28

回答

4

試圖用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) 
+0

謝謝WoLpH,感謝您的幫助。我試過你的解決方案,但仍然遇到一些麻煩。具體來說,當我最後調用save()時,我得到AttribueError異常「StringIO實例沒有屬性'name'」 ------------------ img_temp = StringIO .StringIO(); inImage.save(img_temp,format ='PNG'); img_temp.seek(0); – 2010-08-10 06:17:55

+1

@Joe J:當使用'StringIO'時,'filename'參數是強制性的。那是你現在的問題;) – Wolph 2010-08-10 10:14:53

+0

再次感謝WoLpH。文件名是否必須與文件系統上的路徑相對應,還是隻能是臨時文件的一些隨機名稱? – 2010-08-10 18:23:10