Python 通过Tornado模板中的StringIO/BytesIO动态提供图像

Python 通过Tornado模板中的StringIO/BytesIO动态提供图像,python,tornado,jinja2,Python,Tornado,Jinja2,如何将嵌入到Tornado模板中的图像显示为页面,而不是将其呈现在单独的Tornado处理程序中 我希望通过StringIO/ByesIO为图像提供服务,因为我最终会将图像存储在数据库中 我很抱歉包含了这么多代码。这可能会使文章过于本地化,但该代码只是加载一个图像 将图像作为新页面写入 class DemoHandler(BaseHandler): @tornado.web.asynchronous def get(self): f = Image.open('i

如何将嵌入到Tornado模板中的图像显示为页面,而不是将其呈现在单独的Tornado处理程序中

我希望通过StringIO/ByesIO为图像提供服务,因为我最终会将图像存储在数据库中

我很抱歉包含了这么多代码。这可能会使文章过于本地化,但该代码只是加载一个图像

将图像作为新页面写入

class DemoHandler(BaseHandler):
    @tornado.web.asynchronous
    def get(self):
        f = Image.open('img/cat.jpeg')
        o = io.BytesIO()
        f.save(o, format="JPEG")
        s = o.getvalue()
        self.set_header('Content-type', 'image/jpg')
        self.set_header('Content-length', len(s))   
        self.write(s)   
        self.render('demo.html')

模板:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import division

from base64 import b64encode
from PIL import Image
import tornado
import tornado.ioloop
import tornado.web
import collections
import logging
import re
import os
import io

from tornado.options import define, options
define('port', default=8888, help='Listening port', type=int)

class Application(tornado.web.Application):
    def __init__(self):
        handlers=[
            (r'/\/?', DemoHandler),
        ]
        settings = dict(
            template_path=os.path.dirname(os.path.abspath(__file__)),
            static_path=os.path.dirname(os.path.abspath(__file__)),
            xsrf_cookies=True,
            cookie_secret=b64encode(os.urandom(64)),
            debug=True,
            auto_reload=True,
        )
        tornado.web.Application.__init__(self, handlers, **settings)

        # Configure logging
        options.log_file_max_size = (1024**2)*10
        logging.getLogger().setLevel(logging.INFO)
        tornado.log.enable_pretty_logging()

        print("Listening on port: %d" % options.port)

class BaseHandler(tornado.web.RequestHandler):
    pass

class DemoHandler(BaseHandler):
    @tornado.web.asynchronous
    def get(self):
        f = Image.open('img/cat.jpg')
        o = io.BytesIO()
        f.save(o, format="JPEG")
        s = o.getvalue()    

        user = collections.defaultdict(lambda: collections.defaultdict(dict))
        user['photo']=s

        self.render('demo.html', user=user)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = Application()
    app.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
...
<img src="/img/{{filename}}" style="width:125px;height:125px;"/>
...


UnicodeDecodeError:“utf-8”编解码器无法解码位置0中的字节0xff:无效的开始字节

在其他处理程序中呈现图像。比如:

class ImageHandler(BaseHandler):
    @tornado.web.asynchronous
    def get(self, filename):
        f = Image.open('img/' + filename)
        o = io.BytesIO()
        f.save(o, format="JPEG")
        s = o.getvalue()
        self.set_header('Content-type', 'image/jpg')
        self.set_header('Content-length', len(s))   
        self.write(s)   


class PageHandler(BaseHandler):
    @tornado.web.asynchronous
    def get(self):
        self.render('demo.html', filename=)

class Application(tornado.web.Application):
    def __init__(self):
        handlers=[
            (r'/', PageHandler),
            (r'/img/(?P<filename>.+\.jpg)?', ImageHandler),
        ]
类ImageHandler(BaseHandler):
@tornado.web.asynchronous
def get(自我,文件名):
f=Image.open('img/'+文件名)
o=io.BytesIO()
f、 保存(o,format=“JPEG”)
s=o.getvalue()
self.set_头('Content-type','image/jpg'))
self.set_标题(“内容长度”,长度))
自述
类PageHandler(BaseHandler):
@tornado.web.asynchronous
def get(自我):
self.render('demo.html',文件名=)
类应用程序(tornado.web.Application):
定义初始化(自):
处理者=[
(r'/',PageHandler),
(r'/img/(?P.+\.jpg)?,ImageHandler),
]
模板:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import division

from base64 import b64encode
from PIL import Image
import tornado
import tornado.ioloop
import tornado.web
import collections
import logging
import re
import os
import io

from tornado.options import define, options
define('port', default=8888, help='Listening port', type=int)

class Application(tornado.web.Application):
    def __init__(self):
        handlers=[
            (r'/\/?', DemoHandler),
        ]
        settings = dict(
            template_path=os.path.dirname(os.path.abspath(__file__)),
            static_path=os.path.dirname(os.path.abspath(__file__)),
            xsrf_cookies=True,
            cookie_secret=b64encode(os.urandom(64)),
            debug=True,
            auto_reload=True,
        )
        tornado.web.Application.__init__(self, handlers, **settings)

        # Configure logging
        options.log_file_max_size = (1024**2)*10
        logging.getLogger().setLevel(logging.INFO)
        tornado.log.enable_pretty_logging()

        print("Listening on port: %d" % options.port)

class BaseHandler(tornado.web.RequestHandler):
    pass

class DemoHandler(BaseHandler):
    @tornado.web.asynchronous
    def get(self):
        f = Image.open('img/cat.jpg')
        o = io.BytesIO()
        f.save(o, format="JPEG")
        s = o.getvalue()    

        user = collections.defaultdict(lambda: collections.defaultdict(dict))
        user['photo']=s

        self.render('demo.html', user=user)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = Application()
    app.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
...
<img src="/img/{{filename}}" style="width:125px;height:125px;"/>
...
。。。
...
当然,您可以将图像嵌入到网页中(如此处:),但很少这样做,浏览器缓存性能将受到影响


顺便说一下,使映像i/o异步可能会使您受益。

预期的输出是什么?为什么要将JPEG数据和HTML与
图像/jpg
MIME类型结合起来?预期的输出是包含其他页面内容的图像,例如用户名等。我犯了这些愚蠢的错误,因为我不熟悉web开发-我倾向于坚持后端开发。不确定这是为什么。它看起来很有趣,但不起作用。filename=对于模板调用为空!?我相信原因是,除了明显的打字错误,它是有效的。如果我能复制它,那就太好了。如果您可以更改代码示例?