使用WSGI创建动态图像,无需文件

3 投票
4 回答
4252 浏览
提问于 2025-04-15 12:16

我想给我的用户发送动态生成的图片,比如图表、图形等等。这些图片是“临时”的,只会发送给一个用户,然后就会被销毁,所以“没有文件涉及”。

我希望能直接把图片发送给用户,而不需要先把它保存在文件系统里。在PHP中,可以通过在HTML文件中链接一个图片到一个PHP脚本来实现,比如:

编辑:我的图片标签被吞掉了:

<img src="someScript.php?param1=xyz">

这个脚本会向浏览器发送正确的头信息(比如文件类型是jpeg等),然后直接把图片写回给客户端,而不需要先临时保存到文件系统。

我想知道如何在WSGI应用中做到这一点。目前我使用的是Python自带的SimpleWSGI Server。我知道这个服务器主要是为了演示而设计的,不适合实际使用,因为它不支持多线程,所以请不要再提醒我这一点,我已经意识到了,暂时它满足我的需求 :)

真的像把URL放进图片标签里,然后用WSGI处理请求那么简单吗,还是有更好的做法?

有没有人有过这方面的经验,可以给我一些建议(请不要给我32位的建议)

谢谢,

汤姆

4 个回答

0

你应该考虑使用并关注ETag头信息。虽然这是一个CGI脚本,而不是WSGI,但这些想法是可以互相转化的:sparklines源代码 -- 它总是对相同的参数返回相同的图片,所以它在极限缓存方面做得很好。

2

没错。这就像把网址放到页面上一样简单。

<img src="url_to_my_application">

然后你的应用程序只需要用正确的类型返回它,就像在PHP或者其他语言中一样。这里有个最简单的例子:

def application(environ, start_response):
    data = open('test.jpg', 'rb').read() # simulate entire image on memory
    start_response('200 OK', [('content-type': 'image/jpeg'), 
                              ('content-length', str(len(data)))])
    return [data]

当然,如果你使用框架或者辅助库,它们可能会有一些帮助函数,让你更容易实现这个功能。

我想补充一点,网络服务器并不一定需要多线程功能。如果做得对,你可以在没有线程的情况下也能获得良好的性能。

如果你有一个设计良好的事件循环,可以在不同的请求之间切换,并且以一种不需要线程的方式编写请求处理代码(尽量多次将控制权交还给服务器),你甚至可以获得比使用线程更好的性能,因为线程并不会让事情运行得更快,反而会增加额外的负担。

想了解一个不使用线程的优秀Python网络服务器实现,可以查看 twisted.web

9

这和WSGI、PHP或其他特定的网页技术没有关系。想象一下

<img src="someScript.php?param1=xyz">

一般来说,对于网址 someScript.php?param1=xyz,服务器应该返回一张图片类型的数据,这样就能正常工作了。

举个例子:

from wsgiref.simple_server import make_server

def serveImage(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'image/png')]
    start_response(status, headers)

    return open("about.png", "rb").read()

httpd = make_server('', 8000, serveImage)
httpd.serve_forever()

在这里,任何指向serveImage的链接都会返回一张有效的图片,你可以在任何 img 标签中使用它,或者在其他可以放图片的地方,比如CSS或背景图片。

图片数据可以通过很多第三方库动态生成,比如PIL等。举个例子,使用Python图像库动态生成图片的示例可以参考这个链接:http://lost-theory.org/python/dynamicimg.html

撰写回答