Explain Codes LogoExplain Codes Logo

How to serve static files in Flask

python
static-files
flask
web-development
Anton ShumikhinbyAnton Shumikhin·Sep 23, 2024
TLDR

To serve Flask static files, set the directory path with static_folder. By default, Flask uses the static folder in your application root. You can customize this using Flask(static_folder='your_folder'). To serve files, use send_from_directory to handle requests:

from flask import Flask, send_from_directory app = Flask(__name__, static_folder='my_static') # My castle my rules! @app.route('/files/<path:filename>') def serve_files(filename): return send_from_directory(app.static_folder, filename) # Beware of paper cuts! # Access via http://[hostname]/files/filename

Replace 'your_folder' with the actual folder name and access files at the endpoint /files/<filename>.

Tightening the security

While send_from_directory is highly useful for serving static files, it’s booby trapped with potential security risks especially when working with user inputs. Be cautious not to expose direct file paths! Validate filenames on the server-side before courting danger:

@app.route('/safe-files/<path:filename>') def safe_serve_files(filename): if is_safe_path(app.static_folder, filename): # Safety dance! return send_from_directory(app.static_folder, filename) return abort(404) # "These aren't the files you're looking for."

Design is_safe_path() to cross-examine if the requested file is within your static directory and is not a trap.

For permissions check and more advanced logics before serving the file, feel free to add more steps in the dance.

Getting the house in order for the big party

When switching to the production environment, remember to get the heavy-lifting done by a professional mover. In other words, delegate the serving of static files to a dedicated web server like Nginx or Apache. This lets Flask focus on creating new and dynamic content.

# Nginx configuration location /static { alias /path/to/your/app/static; # Movers handle heavy stuff with ease }

Lessen URL's verbal diarhea by static_url_path and shift the location on the server-side with static_folder if needed. For instance, setting static_url_path='' lets you say ‘/filename’ instead of '/static/filename'. Sweet & short!

Tweaking templates and vivifying virtual files

The template_folder parameter is to Flask templates what spinach is to Popeye, it adds more muscle power. Moreover, you don't have to stick to serving static files from the file system alone. Flask's send_file function plays nice with in-memory files like a BytesIO object:

from flask import send_file from io import BytesIO @app.route('/generate-file') def generate_file(): mem = BytesIO() mem.write(b'Some dynamically created file content') # Mem's the word! mem.seek(0) return send_file(mem, as_attachment=True, attachment_filename='dynamic.txt')

URL building best practices and hitching HTML with static files

Leverage Flask's url_for function in your HTML templates to build URLs smartly:

<img src="{{ url_for('static', filename='images/logo.png') }}">

Just as you would delegate serving files to a dedicated server in a production environment, you can also use Flask extensions or even CDNs to serve a cached and optimized version of your static assets.