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)
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With