2010-08-18 78 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)