Python Tornado如何在任意位置为单个静态文件提供服务?
我正在用Tornado开发一个简单的web应用程序。它提供一些动态文件和一些静态文件。动态文件不是问题,但我在提供静态文件时遇到了问题。我想做的是在访问/foo.json URL时提供文件/path/to/foo.json 请注意/path/to/foo.json位于文档根目录之外。在Apache中,我只需要设置一个别名。关于龙卷风,我有:Python Tornado如何在任意位置为单个静态文件提供服务?,python,tornado,static-files,Python,Tornado,Static Files,我正在用Tornado开发一个简单的web应用程序。它提供一些动态文件和一些静态文件。动态文件不是问题,但我在提供静态文件时遇到了问题。我想做的是在访问/foo.json URL时提供文件/path/to/foo.json 请注意/path/to/foo.json位于文档根目录之外。在Apache中,我只需要设置一个别名。关于龙卷风,我有: app = tornado.web.Application([ (r'/dynamic\.html', MyService, dict(param
app = tornado.web.Application([
(r'/dynamic\.html', MyService, dict(param = 12345)),
(r'/(foo\.json)', tornado.web.StaticFileHandler, {'path': '/path/to/foo.json'})
])
我添加了正则表达式组操作符()
,以满足Tornado的要求,否则会引发异常。但是现在,当我访问/foo.json时,我得到一个404:File Not Found
测试显示Tornado试图使用作为根目录提供的路径,并将foo.json附加到根目录,这意味着如果我的文件位于/path/to/foo.json/foo.json,就可以找到我的文件。很接近,但不完全一样
我想我可以简单地将路径缩短为“/path/to”,这将在/foo.json URL上触发/path/to/foo.json的获取,但这会迫使我在URL中使用与文件系统相同的名称。我怎样才能做一个简单的,任意的,URL到文件的映射呢
我对此做了一些研究,阅读了和的文档,还有一些。没有什么是我的用例。像这样的东西应该可以工作:
import os
import tornado.ioloop
import tornado.web
class MyFileHandler(tornado.web.StaticFileHandler):
def initialize(self, path):
self.dirname, self.filename = os.path.split(path)
super(MyFileHandler, self).initialize(self.dirname)
def get(self, path=None, include_body=True):
# Ignore 'path'.
super(MyFileHandler, self).get(self.filename, include_body)
app = tornado.web.Application([
(r'/foo\.json', MyFileHandler, {'path': '/path/to/foo.json'})
])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
URL模式和文件名不需要关联,您可以这样做,也可以这样做:
app = tornado.web.Application([
(r'/jesse\.txt', MyFileHandler, {'path': '/path/to/foo.json'})
])
StaticFileHandler从正则表达式捕获组获取文件名,从其path参数获取目录名。如果您使用
/path/to/
作为路径,则它将起作用:
(r'/(foo\.json)', tornado.web.StaticFileHandler, {'path': '/path/to/'})
StaticFileHandler设计用于URL和文件名匹配的情况;如果您无法安排以相同的名称在磁盘上提供此文件,则需要使用自定义处理程序来提供此文件 StaticFileHandler需要两个参数,因此如果希望将单个url(/foo.json)映射到文件路径,可以使用:
app = tornado.web.Application([
(r'/foo.json()', tornado.web.StaticFileHandler, {'path': '/path/to/foo.json'})
])
正则表达式将匹配
/foo.json
,并发送空的捕获组()
,这将导致文件路径按原样使用。当捕获组不为空时,/path/to/foo.json
将被视为目录/path/to/foo.json/
,处理程序将尝试将捕获组中的任何内容与该目录中的文件名相匹配 因此,通过任意文件映射,您想要的就是将URLyourdomain.com/path/to/foo.json
映射到yourfilesystem/path/to/bar.json
?我认为你应该在你的问题中包括这一点(即,在示例中使用不同的名称,而不是在URL和文件系统中使用foo.json
),我在我的倒数第二段@justhalf中提到了这一点,但可能会更清楚。是的,我的观点是在你的示例中包括你在倒数第二段中提到的内容。因为您的示例并不真正代表您真正的问题。请注意,子类化StaticFileHandler可能很微妙,最好不要使用get()
。相反,classmethodget\u absolute\u path
是一个更好的重写方法()我喜欢这种方法,它对我来说很好。但是我对覆盖get\u absolute\u path
的方法很感兴趣@BenDarnell,你能提供一个例子吗?这是未经测试的,但它说明了一般的想法:但是get_absolute_path是一个类方法,没有“self”。谢谢你,Mark。我喜欢这种方法的简单性+1.为什么没有括号?