如何在 Flask 中提供静态文件
P粉754473468
2023-08-23 15:50:41
<p>所以这很尴尬。我在 <code>Flask</code> 中组装了一个应用程序,目前它仅提供一个静态 HTML 页面,其中包含一些指向 CSS 和 JS 的链接。我在文档 <code>Flask</code> 中找不到描述返回静态文件的位置。是的,我可以使用 <code>render_template</code> 但我知道数据没有模板化。我认为 <code>send_file</code> 或 <code>url_for</code> 是正确的,但我无法让它们工作。与此同时,我打开文件,读取内容,并使用适当的 mimetype 来设置 <code>Response</code>:</p>
<pre class="brush:php;toolbar:false;">import os.path
from flask import Flask, Response
app = Flask(__name__)
app.config.from_object(__name__)
def root_dir(): # pragma: no cover
return os.path.abspath(os.path.dirname(__file__))
def get_file(filename): # pragma: no cover
try:
src = os.path.join(root_dir(), filename)
# Figure out how flask returns static files
# Tried:
# - render_template
# - send_file
# This should not be so non-obvious
return open(src).read()
except IOError as exc:
return str(exc)
@app.route('/', methods=['GET'])
def metrics(): # pragma: no cover
content = get_file('jenkins_analytics.html')
return Response(content, mimetype="text/html")
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def get_resource(path): # pragma: no cover
mimetypes = {
".css": "text/css",
".html": "text/html",
".js": "application/javascript",
}
complete_path = os.path.join(root_dir(), path)
ext = os.path.splitext(path)[1]
mimetype = mimetypes.get(ext, "text/html")
content = get_file(complete_path)
return Response(content, mimetype=mimetype)
if __name__ == '__main__': # pragma: no cover
app.run(port=80)</pre>
<p>有人想为此提供代码示例或网址吗?我知道这会非常简单。</p>
如果您只想移动静态文件的位置,那么最简单的方法是在构造函数中声明路径。在下面的示例中,我已将模板和静态文件移动到名为
web
的子文件夹中。static_url_path=''
从 URL 中删除所有前面的路径。static_folder='web/static'
提供在文件夹中找到的任何文件web/static
作为静态文件。template_folder='web/templates'
类似地,这会更改 模板文件夹。使用此方法,以下 URL 将返回 CSS 文件:
最后,这是文件夹结构的快照,其中
flask_server.py
是 Flask 实例:在生产中,在应用程序前面配置 HTTP 服务器(Nginx、Apache 等),以处理来自静态文件夹的
/static
请求。专用 Web 服务器非常擅长高效地提供静态文件,尽管在低容量时您可能不会注意到与 Flask 相比的差异。Flask 会自动创建一个
/static/
路由,该路由将为 Python 旁边的static
文件夹下的任何filename
提供服务定义 Flask 应用程序的模块。使用url_for
链接到静态文件:url_for('static', filename='js/analytics.js')
您还可以使用
send_from_directory
来提供文件从您自己的路线中的目录中。这需要一个基本目录和一个路径,并确保该路径包含在该目录中,这样可以安全地接受用户提供的路径。如果您想在提供文件之前检查某些内容,例如登录用户是否具有权限,这可能很有用。请勿将
send_file
或send_static_file
与用户提供的路径一起使用。这将使您面临目录遍历攻击。send_from_directory
旨在安全地处理已知目录下用户提供的路径,如果路径尝试转义该目录,则会引发错误。如果您在内存中生成文件而不将其写入文件系统,则可以将
BytesIO
对象传递给send_file
将其作为文件提供。在这种情况下,您需要将其他参数传递给send_file
,因为它无法推断文件名或内容类型等内容。