如何在 Flask 中提供静态文件

2024-11-18 08:41:00
admin
原创
10
摘要:问题描述:这很尴尬。我有一个自己拼凑起来的应用程序Flask,目前它只提供一个静态 HTML 页面,其中包含一些 CSS 和 JS 链接。而且我在文档中找不到Flask描述返回静态文件的位置。是的,我可以使用render_template,但我知道数据没有模板化。我本以为send_file这url_for是正...

问题描述:

这很尴尬。我有一个自己拼凑起来的应用程序Flask,目前它只提供一个静态 HTML 页面,其中包含一些 CSS 和 JS 链接。而且我在文档中找不到Flask描述返回静态文件的位置。是的,我可以使用render_template,但我知道数据没有模板化。我本以为send_fileurl_for是正确的做法,但我无法让它们发挥作用。与此同时,我正在打开文件、阅读内容,并Response使用适当的 mimetype 进行装配:

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)

有人想给出这个的代码示例或 URL 吗?我知道这会非常简单。


解决方案 1:

在生产中,在应用程序前面配置 HTTP 服务器(Nginx、Apache 等)以处理来自/static静态文件夹的请求。专用 Web 服务器非常擅长高效地处理静态文件,尽管在低容量的情况下,您可能不会注意到与 Flask 相比的差异。

Flask 会自动创建一个路由,该路由将为定义 Flask 应用的 Python 模块旁边的文件夹下的/static/<path:filename>任何内容提供服务。用于链接到静态文件:filename`staticurl_forurl_for('static', filename='js/analytics.js')`

您还可以使用send_from_directory在您自己的路由中从目录提供文件。这需要一个基本目录和一个路径,并确保该路径包含在目录中,这使得接受用户提供的路径变得安全。如果您想在提供文件之前检查某些内容(例如登录用户是否有权限),这很有用。

from flask import send_from_directory

@app.route('/reports/<path:path>')
def send_report(path):
    # Using request args for path will expose you to directory traversal attacks
    return send_from_directory('reports', path)

警告:不要send_filesend_static_file与用户提供的路径一起使用。这会使您遭受目录遍历攻击。 send_from_directory旨在安全地处理已知目录下的用户提供的路径,如果路径试图逃离目录,则会引发错误。

如果您在内存中生成文件而不将其写入文件系统,则可以将对象传递BytesIOsend_file它以将其作为文件提供。在这种情况下,您需要传递其他参数,send_file因为它无法推断文件名或内容类型等信息。

解决方案 2:

如果您只想移动静态文件的位置,那么最简单的方法是在构造函数中声明路径。在下面的示例中,我将模板和静态文件移动到名为的子文件夹中web

app = Flask(__name__,
            static_url_path='', 
            static_folder='web/static',
            template_folder='web/templates')
  • static_url_path=''从 URL 中删除所有前面的路径。

  • static_folder='web/static'将文件夹中找到的所有文件
    web/static作为静态文件提供。

  • template_folder='web/templates'同样,这会改变模板文件夹。

使用此方法,以下 URL 将返回一个 CSS 文件:

<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">

最后,这是文件夹结构的快照,其中flask_server.py是 Flask 实例:

嵌套静态 Flask 文件夹

解决方案 3:

您还可以(这是我最喜欢的)将文件夹设置为静态路径,以便每个人都可以访问里面的文件。

app = Flask(__name__, static_url_path='/static')

通过该设置,您可以使用标准 HTML:

<link rel="stylesheet" type="text/css" href="/static/style.css">

解决方案 4:

我相信你会在那里找到你需要的东西:http://flask.pocoo.org/docs/quickstart/#static-files

基本上,您只需要在包的根目录中有一个“静态”文件夹,然后就可以使用url_for('static', filename='foo.bar')或直接链接到您的文件http://example.com/static/foo.bar

正如评论中所建议的,您可以直接使用'/static/foo.bar'URL 路径,但 url_for()开销(性能方面)相当低,并且使用它意味着您将能够轻松地自定义行为(更改文件夹、更改 URL 路径、将静态文件移动到 S3 等)。

解决方案 5:

您可以使用此功能:

send_static_file(filename)

内部使用的函数,用于将静态文件从静态文件夹发送到浏览器。

app = Flask(__name__)
@app.route('/<path:path>')
def static_file(path):
    return app.send_static_file(path)

解决方案 6:

我使用的(并且效果很好)是“templates”目录和“static”目录。我将所有 .html 文件/Flask 模板放在 templates 目录中,static 包含 CSS/JS。据我所知,render_template 适用于通用 html 文件,无论您使用 Flask 模板语法的程度如何。下面是我的 views.py 文件中的示例调用。

@app.route('/projects')
def projects():
    return render_template("projects.html", title = 'Projects')

当您确实想要引用单独静态目录中的某个静态文件时,请确保使用 url_for()。您可能最终还是会在 html 中的 CSS/JS 文件链接中执行此操作。例如...

<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>

这里有一个“规范的”非正式 Flask 教程的链接 - 这里有很多很棒的提示,可以帮助您快速入门。

http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world

解决方案 7:

根据其他答案的最简单的工作示例如下:

from flask import Flask, request
app = Flask(__name__, static_url_path='')
    
@app.route('/index/')
def root():
    return app.send_static_file('index.html')
    
if __name__ == '__main__':
    app.run(debug=True)

使用名为index.html的 HTML :

<!DOCTYPE html>
<html>
<head>
    <title>Hello World!</title>
</head>
<body>
    <div>
        <p>This is a test.</p>
    </div>
</body>
</html>

重要提示: index.html位于名为 static 的文件夹中意味着<projectpath>有该.py文件,并且<projectpath>static有该html文件。

如果希望服务器在网络上可见,请使用 app.run(debug=True, host='0.0.0.0')

如需显示文件夹中的所有文件(如果需要),请使用此

@app.route('/<path:path>')
def static_file(path):
    return app.send_static_file(path)

这基本上就是BlackMamba的答案,所以给他们点赞吧。

解决方案 8:

对于创建下一个文件夹树的 angular+boilerplate 流程:

backend/
|
|------ui/
|      |------------------build/          <--'static' folder, constructed by Grunt
|      |--<proj           |----vendors/   <-- angular.js and others here
|      |--     folders>   |----src/       <-- your js
|                         |----index.html <-- your SPA entrypoint 
|------<proj
|------     folders>
|
|------view.py  <-- Flask app here

我使用以下解决方案:

...
root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui", "build")

@app.route('/<path:path>', methods=['GET'])
def static_proxy(path):
    return send_from_directory(root, path)


@app.route('/', methods=['GET'])
def redirect_to_index():
    return send_from_directory(root, 'index.html')
...

它有助于将“静态”文件夹重新定义为自定义。

解决方案 9:

app = Flask(__name__, static_folder="your path to static")

如果你的根目录中有模板,则放置 app=Flask( name ) 将起作用,如果包含此文件的文件也位于同一位置,如果此文件位于其他位置,则必须指定模板位置以使 Flask 指向该位置

解决方案 10:

因此我让事情进展顺利(基于@user1671599 的回答)并想与大家分享。

(我希望我做得对,因为这是我用 Python 编写的第一个应用程序)

我这样做了 -

项目结构:

在此处输入图片描述

服务器.py:

from server.AppStarter import AppStarter
import os

static_folder_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "client")

app = AppStarter()
app.register_routes_to_resources(static_folder_root)
app.run(__name__)

AppStarter.py:

from flask import Flask, send_from_directory
from flask_restful import Api, Resource
from server.ApiResources.TodoList import TodoList
from server.ApiResources.Todo import Todo


class AppStarter(Resource):
    def __init__(self):
        self._static_files_root_folder_path = ''  # Default is current folder
        self._app = Flask(__name__)  # , static_folder='client', static_url_path='')
        self._api = Api(self._app)

    def _register_static_server(self, static_files_root_folder_path):
        self._static_files_root_folder_path = static_files_root_folder_path
        self._app.add_url_rule('/<path:file_relative_path_to_root>', 'serve_page', self._serve_page, methods=['GET'])
        self._app.add_url_rule('/', 'index', self._goto_index, methods=['GET'])

    def register_routes_to_resources(self, static_files_root_folder_path):

        self._register_static_server(static_files_root_folder_path)
        self._api.add_resource(TodoList, '/todos')
        self._api.add_resource(Todo, '/todos/<todo_id>')

    def _goto_index(self):
        return self._serve_page("index.html")

    def _serve_page(self, file_relative_path_to_root):
        return send_from_directory(self._static_files_root_folder_path, file_relative_path_to_root)

    def run(self, module_name):
        if module_name == '__main__':
            self._app.run(debug=True)

解决方案 11:

默认情况下,名为“static”的文件夹包含所有静态文件这是一个代码示例:

<link href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">

解决方案 12:

使用redirecturl_for

from flask import redirect, url_for

@app.route('/', methods=['GET'])
def metrics():
    return redirect(url_for('static', filename='jenkins_analytics.html'))

这将为您的 html 中引用的所有文件(css 和 js……)提供服务器。

解决方案 13:

最简单的方法之一。 干杯!

演示文件

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
   return render_template("index.html")

if __name__ == '__main__':
   app.run(debug = True)

现在创建名为templates的文件夹。将index.html文件添加到templates文件夹中

索引.html

<!DOCTYPE html>
<html>
<head>
    <title>Python Web Application</title>
</head>
<body>
    <div>
         <p>
            Welcomes You!!
         </p>
    </div>
</body>
</html>

项目结构

-demo.py
-templates/index.html

解决方案 14:

我遇到的问题与使用和index.html时无法为目录提供文件有关。static_url_path`static_folder`

这是我的解决方案:

import os
from flask import Flask, send_from_directory
from flask.helpers import safe_join

app = Flask(__name__)
static = safe_join(os.path.dirname(__file__), 'static')

@app.route('/')
def _home():
  return send_from_directory(static, 'index.html')

@app.route('/<path:path>')
def _static(path):
  if os.path.isdir(safe_join(static, path)):
    path = os.path.join(path, 'index.html')
  return send_from_directory(static, path)

解决方案 15:

想分享...这个例子。

from flask import Flask
app = Flask(__name__)

@app.route('/loading/')
def hello_world():
    data = open('sample.html').read()    
    return data

if __name__ == '__main__':
    app.run(host='0.0.0.0')

这样效果更好而且更简单。

解决方案 16:

所有答案都很好,但对我来说,使用send_fileFlask 的简单函数效果很好。当你只需要发送一个 html 文件作为响应时,这种方法效果很好,此时host:port/ApiName将在浏览器中显示文件的输出


@app.route('/ApiName')
def ApiFunc():
    try:
        return send_file('some-other-directory-than-root/your-file.extension')
    except Exception as e:
        logging.info(e.args[0])```

解决方案 17:

最简单的方法是在主项目文件夹内创建一个静态文件夹。静态文件夹包含 .css 文件。

主文件夹

/Main Folder
/Main Folder/templates/foo.html
/Main Folder/static/foo.css
/Main Folder/application.py(flask script)

包含静态和模板文件夹以及 Flask 脚本的主文件夹图像

烧瓶

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def login():
    return render_template("login.html")

html(布局)

<!DOCTYPE html>
<html>
    <head>
        <title>Project(1)</title>
        <link rel="stylesheet" href="/static/styles.css">
     </head>
    <body>
        <header>
            <div class="container">
                <nav>
                    <a class="title" href="">Kamook</a>
                    <a class="text" href="">Sign Up</a>
                    <a class="text" href="">Log In</a>
                </nav>
            </div>
        </header>  
        {% block body %}
        {% endblock %}
    </body>
</html>

html

{% extends "layout.html" %}

{% block body %}
    <div class="col">
        <input type="text" name="username" placeholder="Username" required>
        <input type="password" name="password" placeholder="Password" required>
        <input type="submit" value="Login">
    </div>
{% endblock %}

解决方案 18:

可以使用静态端点创建静态文件的 URL,如下所示:

url_for('static', filename = 'name_of_file')
<link rel="stylesheet" href="{{url_for('static', filename='borders.css')}}" />

解决方案 19:

这对我有用:

import os
from flask import Flask, render_template, send_from_directory
app = Flask(__name__)


root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "whereyourfilesare")

@app.route('/', methods=['GET'])
def main(request):
    path = request.path
    if (path == '/'):
        return send_from_directory(root, 'index.html')
    else:
        return send_from_directory(root, path[1:])

解决方案 20:

   默认情况下,flask 使用“templates”文件夹来包含所有模板文件(任何纯文本文件,但通常.html是某种模板语言,例如 jinja2 )和“static”文件夹来包含所有静态文件(即.js .css和您的图像)。

   在您的 中routes,您可以使用render_template()来呈现模板文件(正如我上面所说,默认情况下它放在templates文件夹中)作为对您请求的响应。并且在模板文件(通常是类似 .html 的文件)中,您可能会使用一些.js和/或“.css”文件,所以我想您的问题是如何将这些静态文件链接到当前模板文件。

解决方案 21:

如果你只是想打开一个文件,你可以使用 app.open_resource()。因此,读取文件看起来就像

with app.open_resource('/static/path/yourfile'):
      #code to read the file and do something

解决方案 22:

在静态目录中,创建模板目录,在该目录内添加所有 html 文件,为 css 和 javascript 创建单独的目录,因为 flask 将处理或识别模板目录中的所有 html 文件。

static -
       |_ templates
       |_ css
       |_javascript
       |_images

解决方案 23:

在我的例子中,我需要让用户能够访问静态文件夹中的所有文件,并且我需要对某些 ​​html 文件使用模板,以便将通用 html 代码放在模板中并重复使用代码。以下是我同时实现这两个目标的方法:

from flask import Flask, request, render_template
from flask.json import JSONEncoder

app = Flask(__name__, template_folder='static')


@app.route('/<path:path>')
def serve_static_file(path):
    # In my case, only html files are having the template code inside them, like include.
    if path.endswith('.html'):
        return render_template(path)
    # Serve all other files from the static folder directly.
    return app.send_static_file(path)

我的所有文件都保存在静态文件夹下,与主 flask 文件平行。

在此处输入图片描述

解决方案 24:

例如,要返回我使用过的 Adsense 文件:

@app.route('/ads.txt')
def send_adstxt():
    return send_from_directory(app.static_folder, 'ads.txt')
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用