In this section, we will learn how to handle file uploads in a Flask application. File uploads are a common feature in web applications, allowing users to upload images, documents, and other files. We will cover the following topics:

  1. Setting up the file upload form
  2. Handling file uploads in Flask
  3. Saving uploaded files
  4. Validating file uploads

  1. Setting Up the File Upload Form

First, we need to create an HTML form that allows users to select and upload files. We will use the enctype="multipart/form-data" attribute in the form tag to ensure that the file data is sent correctly.

<!-- templates/upload.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>File Upload</title>
</head>
<body>
    <h1>Upload a File</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="Upload">
    </form>
</body>
</html>

  1. Handling File Uploads in Flask

Next, we need to create a route in our Flask application to handle the file upload. This route will process the form data and save the uploaded file.

# app.py
from flask import Flask, request, redirect, url_for, render_template
import os

app = Flask(__name__)

# Ensure the upload folder exists
UPLOAD_FOLDER = 'uploads'
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

@app.route('/')
def index():
    return render_template('upload.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return 'No file part'
    file = request.files['file']
    if file.filename == '':
        return 'No selected file'
    if file:
        filename = file.filename
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        return 'File successfully uploaded'

if __name__ == '__main__':
    app.run(debug=True)

  1. Saving Uploaded Files

In the above code, we save the uploaded file to a directory specified by UPLOAD_FOLDER. The file.save() method is used to save the file to the server.

Explanation:

  • request.files['file']: Accesses the uploaded file.
  • file.filename: Retrieves the name of the uploaded file.
  • file.save(): Saves the file to the specified directory.

  1. Validating File Uploads

It's important to validate the uploaded files to ensure they meet certain criteria, such as file type and size. We can add validation logic to our upload_file route.

# app.py (continued)
from werkzeug.utils import secure_filename

ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return 'No file part'
    file = request.files['file']
    if file.filename == '':
        return 'No selected file'
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        return 'File successfully uploaded'
    else:
        return 'File type not allowed'

Explanation:

  • allowed_file(filename): Checks if the file extension is in the allowed list.
  • secure_filename(filename): Ensures the filename is secure and safe to use.

Practical Exercise

Exercise:

  1. Create a Flask application that allows users to upload images.
  2. Validate that only image files (png, jpg, jpeg, gif) are allowed.
  3. Save the uploaded images to a directory named uploads.

Solution:

# app.py
from flask import Flask, request, redirect, url_for, render_template
import os
from werkzeug.utils import secure_filename

app = Flask(__name__)

UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def index():
    return render_template('upload.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return 'No file part'
    file = request.files['file']
    if file.filename == '':
        return 'No selected file'
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        return 'File successfully uploaded'
    else:
        return 'File type not allowed'

if __name__ == '__main__':
    app.run(debug=True)

Common Mistakes:

  • Forgetting to set enctype="multipart/form-data" in the form.
  • Not checking if the file part exists in request.files.
  • Not validating the file type before saving.

Additional Tips:

  • Use secure_filename to avoid security issues with filenames.
  • Consider adding more validation, such as file size limits.

Conclusion

In this section, we learned how to handle file uploads in a Flask application. We covered setting up the file upload form, handling file uploads, saving uploaded files, and validating file uploads. With these skills, you can now allow users to upload files to your Flask applications securely and efficiently.

© Copyright 2024. All rights reserved