How to download file using Python Flask

Introduction

Here I am going to show a simple example on how to download a file using Python Flask. I will download the file which is kept in the server location. The file could be any type of file, i.e., pdf, text, excel, word etc. In this example there will be a simple UI (user Interface), where a link will be provided to the user and clicking on the link a file will be download. The downloaded file will ask you to choose a location for saving it.

There could be any reason to download a file from server. The reason could be, you want to generate reports from database and download these reports.

Prerequisites

Python 3.8.0 – 3.9.1, Flask 1.1.1 – 1.1.2 (pip install flask)

Now I will create the web application that will download a any kind of file which is kept on a server location.

Project Directory

First step is to create a project root directory under which I will put all the required files for the project.

Let’s say I am going to create a project root directory python-flask-file-download.

I may not mention the project root directory in subsequent sections while creating new files and I will assume that I am talking with respect to the project’s root directory.

Configuring Flask

Create the below app.py script (py is the extension to indicate Python script) where I import the flask module. This file should be created under the project root directory. Notice how I create flask instance.

from flask import Flask

app = Flask(__name__)

Configuring URLs

Next I will create main.py script that will define all URIs or Action paths for performing certain operations such as rendering the UI and downloading the file from server.

from app import app
from flask import Flask, send_file, render_template
	
@app.route('/')
def upload_form():
	return render_template('download.html')

@app.route('/download')
def download_file():
	#path = "html2pdf.pdf"
	#path = "info.xlsx"
	path = "simple.docx"
	#path = "sample.txt"
	return send_file(path, as_attachment=True)

if __name__ == "__main__":
    app.run()

In the above source code, the root path or endpoint will simply render the UI. This UI contains only one link for downloading a file from the server. Clicking on the link will ask user to save the file in a chosen location.

the endpoint /download is called on clinking upon the link on UI and a file is sent to the client or UI. The file type could be anything. As you see I have tested with four types of files. I hope this example will work with other file types as well.

UI Template

Now create a download.html file and put it under templates directory. templates directory is the standard directory structure of Flask based web application for putting templates or HTMLs or any static resources – js, css, images.

<!doctype html>
<title>Python Flask File Download Example</title>
<h2>Download a file</h2>

<p>
	<a href="{{ url_for('.download_file') }}">Download</a>
</p>

Notice in the above template file I am using Flask EL (Expression language) to evaluate the link endpoint.

Testing the Application

Now navigate to the project root directory from command line tool and execute the command python main.py or simply main.py if your Python is available on class path, your server will start on default port 5000.

If you want to change the port then you can change the line app.run() to app.run(port=50001), where 5001 is the new port.

Home Page

Hitting the URL http://localhost:5000 will show you a page similar to the below image:

download file using python flask

Clicking on the download link will ask you to save the file according to your chosen location.

Source Code

Download

4 thoughts on “How to download file using Python Flask

  1. On some devices, the file is cached, so if the file is updated, you will not download the newest version without having to clear your browser’s cache. Any way to clear the cache from Flask?

    1. You have to stop browser cache using http header response.

      @app.after_request
      def cache_control(response):
      response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
      response.headers['Cache-Control'] = 'public, max-age=0'
      return response

      The @after_request will execute after each request and you don’t need to call this function explicitly.

Leave a Reply

Your email address will not be published. Required fields are marked *