Django与动态生成的图片

5 投票
1 回答
1904 浏览
提问于 2025-04-16 02:58

我在我的Django应用中有一个视图,它会自动生成一张图片,使用的是PIL库,然后把这张图片存储在Nginx的媒体服务器上,最后返回一个包含图片链接的html模板。

这个过程基本上是正常的,但我发现了一个问题。每当我访问这个视图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-Length”是零。这可能是什么原因呢?有没有什么想法可以帮助我进一步调试这个问题?

编辑:当调用这个视图时,它会调用模型中的“draw”方法。这个方法基本上是这样工作的(我为了清晰起见去掉了大部分代码):

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

编辑2:这是网站链接: http://xxxcnn7979.hospedagemdesites.ws:8000/cartao/99/

如果你不断按F5,右边的图片最终会显示出来。

1 个回答

5

我们之前在把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)

撰写回答