Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask Download a File

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)

like image 314
Saimu Avatar asked Jul 04 '14 15:07

Saimu


People also ask

How do I make a file downloadable in Flask?

join function to append the Flask app's root path stored in current_app. root_path and the upload folder's path from the root folder stored in app. config['UPLOAD_FOLDER'] . current_app is the application context.

How do I download a CSV file by clicking a link in python Flask?

Firstly you need to import from flask make_response , that will generate your response and create variable, something like response . Secondly, make response. content_type = "text/csv" Thirdly - return your response.


1 Answers

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.

like image 90
Martijn Pieters Avatar answered Sep 19 '22 09:09

Martijn Pieters