Last modified: Nov 15, 2024 By Alexander Williams
Flask send_from_directory: Serve Files Securely from Directories
Flask's send_from_directory()
function provides a secure way to serve files from specific directories in your web application. It's particularly useful when you need to serve files dynamically.
Basic Usage
Here's how to implement basic file serving using send_from_directory. This approach is more secure than directly exposing your file system through static folders.
from flask import Flask, send_from_directory
app = Flask(__name__)
# Route to serve files from a specific directory
@app.route('/downloads/')
def download_file(filename):
# Serve files from the 'uploads' directory
return send_from_directory('uploads', filename)
if __name__ == '__main__':
app.run(debug=True)
Security Features
Path Traversal Protection: send_from_directory automatically protects against directory traversal attacks by sanitizing the filename parameter.
Like send_file(), it handles proper MIME type detection and secure file serving.
Advanced Configuration
@app.route('/files/')
def serve_file(filename):
return send_from_directory(
'uploads',
filename,
as_attachment=True, # Force download
mimetype='application/pdf', # Specify MIME type
conditional=True # Enable conditional responses
)
Error Handling
It's important to handle file not found scenarios gracefully. Here's how to implement proper error handling:
from flask import abort
import os
@app.route('/secure-files/')
def secure_file(filename):
try:
return send_from_directory('secure_uploads', filename)
except FileNotFoundError:
abort(404) # Return 404 if file doesn't exist
Configuration Options
Key parameters for send_from_directory include:
- directory: The directory where files are stored
- path: The file path within the directory
- as_attachment: Force file download instead of display
Best Practices
Always validate file types and implement proper access controls before serving files:
ALLOWED_EXTENSIONS = {'pdf', 'txt', 'doc'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/safe-downloads/')
def safe_download(filename):
if not allowed_file(filename):
abort(400) # Bad request for invalid file types
return send_from_directory('downloads', filename)
Conclusion
The send_from_directory function provides a secure and efficient way to serve files in Flask applications. Remember to always implement proper security measures and error handling.