[Python] Building a File Upload and Download System with Python Flask

In this article, we’ll explore the fundamentals of building a file upload and download system using Flask, a lightweight web framework for Python. We’ll walk through the code step-by-step, explaining its functionality and incorporating best practices for security and user experience.

Prerequisites:

  • Basic understanding of Python
  • Familiarity with web development concepts (optional)

Setting Up the Flask Application:

Project Creation:

  • Create a new directory for your project.
  • Initialize a virtual environment (recommended for managing dependencies):
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate

Flask Installation:

  • Install Flask using pip:
pip install Flask

Code Breakdown:

Imports:

from flask import Flask, request, jsonify
from flask import current_app, send_from_directory
import os
  • Flask: The core web framework.
  • request, jsonify: Tools for handling user requests and responses.
  • current_app: Provides access to the current application instance.
  • send_from_directory: Used to send files from a specific directory.
  • os: Used for interacting with the operating system (file system).

Flask App Initialisation:

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
  • Flask(__name__): Creates a Flask application instance with its name (__name__ is a special variable).
  • app.config['UPLOAD_FOLDER'] = 'uploads': Configures the upload directory where uploaded files will be saved.

File Upload Functionality:

def allowed_file(filename):
ALLOWED_EXTENSIONS = set(['ips'])
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload_file', methods=['POST'])
def upload_file():
print("Reached file upload")
if request.method == 'POST':
# Check if the file part is present
if 'file' not in request.files:
return jsonify({'error': 'No file part'})
file = request.files['file']
# Check if user selected a file
if file.filename == '':
return jsonify({'error': 'No selected file'})
if file and allowed_file(file.filename):
filename = file.filename # Secure filename can be implemented here
print("File is ", filename)
# Create upload directory if it doesn't exist
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.makedirs(app.config['UPLOAD_FOLDER'])
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
# Call your document reading function here (optional)
# ReadDocumentsRAG.read_document(file_path)
return jsonify({'success': 'File Uploaded'})
else:
return jsonify({'error': 'Invalid file format'})
  • allowed_file(filename): Checks if the uploaded file has a supported extension (here, ‘.ips’).
  • @app.route('/upload_file', methods=['POST']): Defines a route for handling file upload requests. It only accepts POST requests.
  • The function logic handles various scenarios:
  • Checks if the request contains a file part ('file' not in request.files).
  • Ensures a file was selected (file.filename == '').
  • Verifies the file format using allowed_file.
  • Creates the upload directory if it doesn’t exist (os.makedirs).
  • Saves the uploaded file to the specified path.
  • Optionally, you can call your document reading function here to process the uploaded content.
  • Returns success or error messages in JSON format (jsonify).

Example Usage:

If your Flask application is running on localhost:5000 and you want to upload a file named data.csv, the command would be:

curl -X POST -F file=@your_file.txt http://your_flask_app_url/upload_file

Explanation:

  • -X POST: Specifies that you’re making a POST request.
  • -F file=@your_file.txt: Tells cURL to upload the file named your_file.txt as the file parameter in the POST request. Replace your_file.txt with the actual path to your file.
  • http://your_flask_app_url/upload_file: The URL of your Flask application’s endpoint for file uploads.Replace http://your_flask_app_url with the actual URL of your application.

Additional Notes:

  • Make sure to replace your_flask_app_url with the correct URL of your Flask application.
  • You can use the -v flag with cURL to see more detailed output, including the HTTP response.
  • For more complex scenarios, you might need to adjust the command based on your specific requirements, such as adding headers or authentication information.

By following these steps and customizing the command to your needs, you can effectively use cURL to upload files to your Flask application.

Downloading Files in Flask

@app.route("/download/<path:filename>", methods=["GET"])
def download(filename):
downloads = os.path.join(current_app.root_path, "downloadable")
print(downloads + "/" + filename)
return send_from_directory(downloads, filename)

Explanation:

Route Definition:

  • @app.route("/download/<path:filename>", methods=["GET"]): Defines a route for handling file download requests. The <path:filename> part allows for dynamic filename parameters.

File Download Logic:

  • downloads = os.path.join(current_app.root_path, "downloadable"): Constructs the path to the directory where downloadable files are stored. current_app.root_path is the root directory of your Flask application.
  • send_from_directory(downloads, filename): Uses the send_from_directory function to send the specified file from the downloads directory. This function automatically sets the appropriate content type and headers for file downloads.

Key Points:

  • File Location: Ensure that the downloadable directory exists and contains the files you want to make available for download.
  • Dynamic Filenames: The route allows for dynamic filenames, making it flexible for various download scenarios.
  • Content Type and Headers: send_from_directory handles the necessary content type and headers for file downloads, ensuring proper browser behavior.

Example Usage:

If your Flask application is running on localhost:5000 and you want to download a file named report.pdf, the command would be:

curl -O http://localhost:5000/download/report.pdf

This will download the report.pdf file from your Flask application and save it to a local file named report.pdf in your current directory.

Additional Notes:

  • You can customize the local filename by using the -o option instead of -O. For example, -o my_downloaded_file.txt would save the file as my_downloaded_file.txt.
  • If you want to see the downloaded content in the terminal instead of saving it to a file, omit the -O or -o option.
  • You can use the -v flag with cURL to see more detailed output, including the HTTP response and the downloaded content.

By following these steps and customizing the command to your needs, you can effectively use cURL to download files from your Flask application.

Learn more [Python] Building a File Upload and Download System with Python Flask

Leave a Reply