【问题标题】:How can Tornado serve a single static file at an arbitrary location?Tornado 如何在任意位置提供单个静态文件?
【发布时间】:2014-02-10 11:05:40
【问题描述】:

我正在使用 Tornado 开发一个简单的网络应用程序。它提供一些动态文件和一些静态文件。动态文件不是问题,但我无法提供静态文件。我要做的是在访问 /foo.json URL 时提供文件 /path/to/foo.json。

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

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 到文件的映射?

我对此进行了一些研究,阅读了tornado.web.Applicationtornado.web.StaticFilehandler 的文档,以及一些other SO questions。没有什么是我的用例。

【问题讨论】:

  • 所以通过任意文件映射,您想要的是将 URL yourdomain.com/path/to/foo.json 映射到 yourfilesystem/path/to/bar.json?我认为你应该在你的问题中包含它(即,在示例中使用不同的名称,而不是在 URL 和文件系统中使用 foo.json
  • 我在倒数第二段中提到了这一点,@justhalf,但也许它可以更清楚。
  • 是的,我的意思是在您的示例中包含您在倒数第二段中提到的内容。因为您的示例并不能真正代表您的真正问题。

标签: python tornado static-files


【解决方案1】:

这样的事情应该可以工作:

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 可能很微妙,最好不要管get()。相反,classmethod get_absolute_path 是在这里覆盖的更好方法 (tornadoweb.org/en/stable/…)
  • 我喜欢这种方法,它对我来说效果很好。但我对覆盖get_absolute_path 的方法很感兴趣。 @BenDarnell,你能举个例子吗?
  • 这是未经测试的,但它说明了总体思路:gist.github.com/bdarnell/8553378
  • 但是get_absolute_path是一个类方法,没有'self'。
【解决方案2】:

StaticFileHandler 获取的是来自正​​则表达式捕获组的文件名和来自其路径参数的目录名。如果您使用/path/to/ 作为路径,它将起作用:

(r'/(foo\.json)', tornado.web.StaticFileHandler, {'path': '/path/to/'})

StaticFileHandler 专为 URL 和文件名匹配的情况而设计;如果您无法安排在磁盘上以相同的名称提供此文件,则您需要使用它,因为您必须使用自定义处理程序。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 谢谢,马克。我喜欢这种方法的简单性。 +1。
    • 为什么不用括号?
    猜你喜欢
    • 2016-10-25
    • 2020-08-29
    • 1970-01-01
    • 2021-05-10
    • 2014-11-19
    • 2014-01-26
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    相关资源
    最近更新 更多