snippetpythonflaskCriticalCanonical
How to serve static files in Flask
Viewed 0 times
howfilesflaskstaticserve
Problem
I've got an application that I threw together in
Someone want to give a code sample or url for this?
Flask and for now it is just serving up a single static HTML page with some links to CSS and JS. And I can't find where in the documentation Flask describes returning static files. Yes, I could use render_template but I know the data is not templatized. I'd have thought send_file or url_for was the right thing, but I could not get those to work. In the meantime, I am opening the files, reading content, and rigging up a Response with appropriate 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('/')
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)Someone want to give a code sample or url for this?
Solution
In production, configure the HTTP server (Nginx, Apache, etc.) in front of your application to serve requests to
Flask automatically creates a
You can also use
WARNING: Do not use
If you are generating a file in memory without writing it to the filesystem, you can pass a
/static from the static folder. A dedicated web server is very good at serving static files efficiently, although you probably won't notice a difference compared to Flask at low volumes.Flask automatically creates a
/static/ route that will serve any filename under the static folder next to the Python module that defines your Flask app. 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 in the directory, which makes it safe to accept user-provided paths. This can be useful in cases where you want to check something before serving the file, such as if the logged in user has permission.from flask import send_from_directory
@app.route('/reports/')
def send_report(path):
# Using request args for path will expose you to directory traversal attacks
return send_from_directory('reports', path)WARNING: Do not use
send_file or send_static_file with a user-supplied path. This will expose you to directory traversal attacks. send_from_directory was designed to safely handle user-supplied paths under a known directory, and will raise an error if the path attempts to escape the directory.If you are generating a file in memory without writing it to the filesystem, you can pass a
BytesIO object to send_file to serve it like a file. You'll need to pass other arguments to send_file in this case since it can't infer things like the file name or content type.Code Snippets
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)Context
Stack Overflow Q#20646822, score: 973
Revisions (0)
No revisions yet.