2010-08-18 87 views
5

我在我的Django應用程序中有一個視圖,該視圖使用PIL自動創建圖像,將其存儲在Nginx媒體服務器中,並返回一個帶有指向其URL的img標籤的html模板。Django和動態生成的圖像

這工作正常,但我注意到一個問題。每5次訪問一次該視圖,其中1個圖像不會呈現。

我做了一些調查,我發現了一些有趣的事情,這是HTTP響應頭當圖像正確呈現:

Accept-Ranges:bytes 
Connection:keep-alive 
Content-Length:14966 
Content-Type:image/jpeg 
Date:Wed, 18 Aug 2010 15:36:16 GMT 
Last-Modified:Wed, 18 Aug 2010 15:36:16 GMT 
Server:nginx/0.5.33 

,這是頭球時未加載圖片:

Accept-Ranges:bytes 
Connection:keep-alive 
Content-Length:0 
Content-Type:image/jpeg 
Date:Wed, 18 Aug 2010 15:37:47 GMT 
Last-Modified:Wed, 18 Aug 2010 15:37:46 GMT 
Server:nginx/0.5.33 

注意Content-Lenth等於零。這可能導致什麼?關於如何進一步調試此問題的任何想法?

編輯: 當視圖被調用時,它調用這個模型的「繪製」方法。這基本上是做什麼的(我刪除了清晰的大量代碼):

def draw(self): 
    # Open/Creates a file 
    if not self.image: 
     (fd, self.image) = tempfile.mkstemp(dir=settings.IMAGE_PATH, suffix=".jpeg") 
     fd2 = os.fdopen(fd, "wb") 
    else: 
     fd2 = open(os.path.join(settings.SITE_ROOT, self.image), "wb") 

    # Creates a PIL Image 
    im = Image.new(mode, (width, height)) 

    # Do some drawing 
    ..... 

    # Saves 
    im = im.resize((self.get_size_site(self.width), 
        self.get_size_site(self.height))) 
    im.save(fd2, "JPEG") 
    fd2.close() 

EDIT2:這是網站: http://xxxcnn7979.hospedagemdesites.ws:8000/cartao/99/

,如果你不停的按F5鍵右側的圖像會最終呈現。

+0

當內容長度爲零,你可以告訴我們,如果成功生成的圖像,並在服務器上存在? – 2010-08-18 17:29:37

+0

是的,它是正確生成的,當您嘗試直接訪問它打開的圖像URL。 – 2010-08-19 14:21:29

+0

爲什麼追加並改變get查詢字符串? – 2010-08-23 23:43:14

回答

4

在將HTML頁面寫入磁盤時,我們曾經遇到過這個問題。我們的解決方案是寫入臨時文件,然後原子重命名文件。您可能還想考慮使用fsync

完整的源代碼可以在這裏找到:staticgenerator/__init__.py,但這裏是有用位:

import os 
import stat 
import tempfile 

... 

f, tmpname = tempfile.mkstemp(dir=directory) 
os.write(f, content) 
# See http://docs.python.org/library/os.html#os.fsync 
f.flush() 
os.fsync(f.fileno()) 
os.close(f) 
# Ensure it is webserver readable 
os.chmod(tmpname, stat.S_IREAD | stat.S_IWRITE | stat.S_IWUSR | stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) 
# Rename is an atomic operation in POSIX 
# See: http://docs.python.org/library/os.html#os.rename 
os.rename(tmpname, fn)