Python Tornado如何在任意位置为单个静态文件提供服务?

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

我正在用Tornado开发一个简单的web应用程序。它提供一些动态文件和一些静态文件。动态文件不是问题,但我在提供静态文件时遇到了问题。我想做的是在访问/foo.json URL时提供文件/path/to/foo.json

请注意/path/to/foo.json位于文档根目录之外。在Apache中,我只需要设置一个别名。关于龙卷风,我有:

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/
,处理程序将尝试将捕获组中的任何内容与该目录中的文件名相匹配

因此,通过任意文件映射,您想要的就是将URL
yourdomain.com/path/to/foo.json
映射到
yourfilesystem/path/to/bar.json
?我认为你应该在你的问题中包括这一点(即,在示例中使用不同的名称,而不是在URL和文件系统中使用
foo.json
),我在我的倒数第二段@justhalf中提到了这一点,但可能会更清楚。是的,我的观点是在你的示例中包括你在倒数第二段中提到的内容。因为您的示例并不真正代表您真正的问题。请注意,子类化StaticFileHandler可能很微妙,最好不要使用
get()
。相反,classmethod
get\u absolute\u path
是一个更好的重写方法()我喜欢这种方法,它对我来说很好。但是我对覆盖
get\u absolute\u path
的方法很感兴趣@BenDarnell,你能提供一个例子吗?这是未经测试的,但它说明了一般的想法:但是get_absolute_path是一个类方法,没有“self”。谢谢你,Mark。我喜欢这种方法的简单性+1.为什么没有括号?