使用WSGI创建动态图像,无需文件
我想给我的用户发送动态生成的图片,比如图表、图形等等。这些图片是“临时”的,只会发送给一个用户,然后就会被销毁,所以“没有文件涉及”。
我希望能直接把图片发送给用户,而不需要先把它保存在文件系统里。在PHP中,可以通过在HTML文件中链接一个图片到一个PHP脚本来实现,比如:
编辑:我的图片标签被吞掉了:
<img src="someScript.php?param1=xyz">
这个脚本会向浏览器发送正确的头信息(比如文件类型是jpeg等),然后直接把图片写回给客户端,而不需要先临时保存到文件系统。
我想知道如何在WSGI应用中做到这一点。目前我使用的是Python自带的SimpleWSGI Server。我知道这个服务器主要是为了演示而设计的,不适合实际使用,因为它不支持多线程,所以请不要再提醒我这一点,我已经意识到了,暂时它满足我的需求 :)
真的像把URL放进图片标签里,然后用WSGI处理请求那么简单吗,还是有更好的做法?
有没有人有过这方面的经验,可以给我一些建议(请不要给我32位的建议)
谢谢,
汤姆
4 个回答
你应该考虑使用并关注ETag头信息。虽然这是一个CGI脚本,而不是WSGI,但这些想法是可以互相转化的:sparklines源代码 -- 它总是对相同的参数返回相同的图片,所以它在极限缓存方面做得很好。
没错。这就像把网址放到页面上一样简单。
<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。
这和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