Contents
File Uploads and Handling in Flask
File uploads are a common feature in web applications, whether it’s for profile pictures, documents, or other types of content. Flask makes it easy to handle file uploads, validate them for security, serve them to users, and manage file paths in a database.
Setting Up File Uploads in a Flask Application
To handle file uploads in Flask, you need to set up a form in your HTML, configure Flask to handle file uploads, and write the necessary routes to process these uploads.
Step 1: Configure Flask for File Uploads
Start by configuring your Flask application to specify the folder where uploaded files should be stored and set a limit on the file size:
from flask import Flask, render_template, request, redirect, url_for, flash
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads/' # Folder to store uploaded files
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB limit
app.secret_key = 'your_secret_key'
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.makedirs(app.config['UPLOAD_FOLDER'])
Step 2: Create an HTML Form for File Uploads
In your templates
folder, create an HTML form that allows users to upload files:
Upload File
Upload a File
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% endwith %}
Step 3: Write the Route to Handle File Uploads
In your app.py
, write a route that handles the file upload:
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# Check if the post request has the file part
if 'file' not in request.files:
flash('No file part', 'danger')
return redirect(request.url)
file = request.files['file']
# If the user does not select a file, the browser may submit an empty part without filename
if file.filename == '':
flash('No selected file', 'danger')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
flash(f'File successfully uploaded: {filename}', 'success')
return redirect(url_for('upload_file'))
return render_template('upload.html')
allowed_file
: This function checks if the file has an allowed extension (for security).secure_filename
: This utility function ensures that the uploaded file’s name is secure, preventing path traversal attacks.file.save
: This saves the file to the specified directory on the server.
Validating and Securing File Uploads
To prevent security risks, you must validate file uploads and ensure that only allowed file types are accepted.
Step 1: Validate File Type
As shown above, you can validate file types by checking the file extension using the allowed_file
function. This is a basic but effective way to restrict the types of files that can be uploaded.
Step 2: Secure the Filename
Using secure_filename
from werkzeug.utils
ensures that the filename is safe to use on your filesystem. It strips any potentially dangerous characters and ensures that the file is saved with a safe name.
Step 3: Set Maximum File Size
By configuring MAX_CONTENT_LENGTH
, you can limit the size of uploaded files, protecting your server from excessively large uploads.
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB limit
If a user tries to upload a file that exceeds this limit, Flask will return a 413 Request Entity Too Large
error.
Serving Uploaded Files to Users
Once files are uploaded, you might need to serve them to users, for example, displaying profile pictures or allowing users to download files.
Step 1: Serve Files Using a Static Route
Flask can serve files from the UPLOAD_FOLDER
using the send_from_directory
function:
from flask import send_from_directory
@app.route('/uploads/')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
Now, users can access their uploaded files by visiting http://127.0.0.1:5000/uploads/filename
.
Step 2: Link to Uploaded Files in HTML
You can create links to uploaded files in your HTML templates:
Storing and Managing File Paths in the Database
To keep track of uploaded files, you should store their paths in a database. This allows you to associate files with users or other entities in your application.
Step 1: Define a Model for File Storage
Create a model in app.py
to store file paths:
class UploadedFile(db.Model):
id = db.Column(db.Integer, primary_key=True)
filename = db.Column(db.String(255), nullable=False)
filepath = db.Column(db.String(255), nullable=False)
upload_date = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return f"UploadedFile('{self.filename}', '{self.filepath}')"
Step 2: Store File Information When Uploading
Modify the upload_file
route to store file information in the database after a successful upload:
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part', 'danger')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No selected file', 'danger')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
# Save file info to the database
uploaded_file = UploadedFile(filename=filename, filepath=filepath)
db.session.add(uploaded_file)
db.session.commit()
flash(f'File successfully uploaded: {filename}', 'success')
return redirect(url_for('upload_file'))
return render_template('upload.html')
Step 3: Retrieve and Display Uploaded Files
You can retrieve and display uploaded files from the database:
@app.route('/files')
def list_files():
files = UploadedFile.query.all()
return render_template('files.html', files=files)
In files.html
, you can display the list of files:
{% for file in files %}
- {{ file.filename }}
{% endfor %}
Summary
Handling file uploads in Flask involves setting up a secure and efficient upload process, validating file types, serving files to users, and storing file paths in a database. By following these steps, you can manage file uploads in your Flask applications effectively while maintaining security and organization.
Related Chapters
- What is Flask?
- Setting Up the Development Environment
- Your First Flask Application
- Understanding Flask Routing
- Rendering Templates
- Working with Forms
- Working with Databases
- User Authentication
- File Uploads and Handling
- RESTful APIs with Flask
- Application Configuration and Deployment
- Testing in Flask
- Flask Extensions
- Handling Error Pages
- Planning the Project
- Developing the Backend with Flask
- Developing the Frontend
- Deployment and Scaling