Flask Download a File

PythonFlaskDownloadFlask Sqlalchemy

Python Problem Overview


I'm trying to create a web app with Flask that lets a user upload a file and serve them to another user. Right now, I can upload the file to the upload_folder correctly. But I can't seem to find a way to let the user download it back.

I'm storing the name of the filename into a database.

I have a view serving the database objects. I can delete them too.

@app.route('/dashboard', methods=['GET', 'POST'])
def dashboard():

    problemes = Probleme.query.all()

    if 'user' not in session:
        return redirect(url_for('login'))

    if request.method == 'POST':
        delete = Probleme.query.filter_by(id=request.form['del_button']).first()
        db.session.delete(delete)
        db.session.commit()
        return redirect(url_for('dashboard'))

    return render_template('dashboard.html', problemes=problemes)

In my HTML I have:

<td><a href="{{ url_for('download', filename=probleme.facture) }}">Facture</a></td>

and a download view :

@app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
    return send_from_directory(directory=app.config['UPLOAD_FOLDER'], filename=filename)

But it's returning :

> Not Found

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

I just want to link the filename to the object and let the user download it (For every object in the same view)

Python Solutions


Solution 1 - Python

You need to make sure that the value you pass to the directory argument is an absolute path, corrected for the current location of your application.

The best way to do this is to configure UPLOAD_FOLDER as a relative path (no leading slash), then make it absolute by prepending current_app.root_path:

@app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
    uploads = os.path.join(current_app.root_path, app.config['UPLOAD_FOLDER'])
    return send_from_directory(directory=uploads, filename=filename)

It is important to reiterate that UPLOAD_FOLDER must be relative for this to work, e.g. not start with a /.

A relative path could work but relies too much on the current working directory being set to the place where your Flask code lives. This may not always be the case.

Solution 2 - Python

> To download file on flask call. File name is Examples.pdf > When I am hitting 127.0.0.1:5000/download it should get > download.

Example:

from flask import Flask
from flask import send_file
app = Flask(__name__)

@app.route('/download')
def downloadFile ():
    #For windows you need to use drive name [ex: F:/Example.pdf]
    path = "/Examples.pdf"
    return send_file(path, as_attachment=True)

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

Solution 3 - Python

I was also developing a similar application. I was also getting not found error even though the file was there. This solve my problem. I mention my download folder in 'static_folder':

app = Flask(__name__,static_folder='pdf')

My code for the download is as follows:

@app.route('/pdf/<path:filename>', methods=['GET', 'POST'])
def download(filename):    
    return send_from_directory(directory='pdf', filename=filename)

This is how I am calling my file from html.

<a class="label label-primary" href=/pdf/{{  post.hashVal }}.pdf target="_blank"  style="margin-right: 5px;">Download pdf </a>
<a class="label label-primary" href=/pdf/{{  post.hashVal }}.png target="_blank"  style="margin-right: 5px;">Download png </a>

Solution 4 - Python

#HTML Code
 
<ul>
 {% for file in files %}
  <li> <a href="{{ url_for('download', filename=file) }}">{{ file }}</a></li>
 {% endfor %}
</ul>


#Python Code

from flask import send_from_directory

app.config['UPLOAD_FOLDER']='logs'


@app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
def download(filename):
    print(app.root_path)
    full_path = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])
    print(full_path)
    return send_from_directory(full_path, filename)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSaimuView Question on Stackoverflow
Solution 1 - PythonMartijn PietersView Answer on Stackoverflow
Solution 2 - PythonViraj WadateView Answer on Stackoverflow
Solution 3 - PythonWaqar DethoView Answer on Stackoverflow
Solution 4 - PythonGaurav NagarView Answer on Stackoverflow