Home  >  Q&A  >  body text

How to serve static files in Flask

<p>So this is embarrassing. I've put together an app in <code>Flask</code> and currently it just serves a static HTML page with some links to CSS and JS. I can't find a place in the documentation for <code>Flask</code> that describes returning static files. Yes, I can use <code>render_template</code> but I know the data is not templated. I think <code>send_file</code> or <code>url_for</code> are correct, but I can't get them to work. In the meantime, I open the file, read the contents, and set the <code>Response</code> using the appropriate mimetype: </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>Does anyone want to provide a code sample or URL for this? I knew it would be very simple. </p>
P粉754473468P粉754473468423 days ago516

reply all(2)I'll reply

  • P粉155551728

    P粉1555517282023-08-24 12:55:28

    If you just want to move the location of the static files, the easiest way is to declare the path in the constructor. In the example below, I've moved the templates and static files into a subfolder called web.

    app = Flask(__name__,
                static_url_path='', 
                static_folder='web/static',
                template_folder='web/templates')
    • static_url_path='' Remove all preceding paths from the URL.
    • static_folder='web/static' Serves any files found in the folder web/static As a static file.
    • template_folder='web/templates' Similarly, this changes Template folder.

    Using this method, the following URL will return the CSS file:

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

    Finally, here is a snapshot of the folder structure, where flask_server.py is the Flask instance:

    reply
    0
  • P粉212971745

    P粉2129717452023-08-24 09:31:38

    In production, configure an HTTP server (Nginx, Apache, etc.) in front of the application to handle /static requests from the static folder. Dedicated web servers are very good at serving static files efficiently, although at low volumes you may not notice the difference compared to Flask.

    Flask will automatically create a /static/ route that will serve any filename under the static folder next to Python Modules that define Flask applications. Use url_for to link to static files: url_for('static', filename='js/analytics.js')

    You can also use send_from_directory to serve files from a directory in your own route. This takes a base directory and a path, and ensures that the path is contained within that directory so that user-supplied paths can be safely accepted. This can be useful if you want to check something before serving the file, such as whether the logged in user has permissions.

    from flask import send_from_directory
    
    @app.route('/reports/<path:path>')
    def send_report(path):
        return send_from_directory('reports', path)

    Do not use send_file or send_static_file with a user-supplied path. This will expose you to a directory traversal attack. send_from_directory Designed to safely handle user-supplied paths to known directories, raising an error if the path attempts to escape the directory.

    If you are generating the file in memory without writing it to the file system, you can provide it as a file by passing a BytesIO object to send_file . In this case you need to pass additional parameters to send_file as it cannot infer things like filename or content type.

    reply
    0
  • Cancelreply