Reputation: 80
Hi I currently have a flask app that shows files and their details, now I want flask to also allow file downloads from the page of the represented file
I tried a couple things including send_from_directory() which didn't work. So my question is how can I add a working download link to the page?
@app.route('/browser/<path:urlFilePath>')
def browser(urlFilePath):
nestedFilePath = os.path.join(FILE_SYSTEM_ROOT, urlFilePath)
if os.path.isdir(nestedFilePath):
itemList = os.listdir(nestedFilePath)
fileProperties = {"filepath": nestedFilePath}
if not urlFilePath.startswith("/"):
urlFilePath = "/" + urlFilePath
return render_template('browse.html', urlFilePath=urlFilePath, itemList=itemList)
if os.path.isfile(nestedFilePath):
fileProperties = {"filepath": nestedFilePath}
sbuf = os.fstat(os.open(nestedFilePath, os.O_RDONLY)) #Opening the file and getting metadata
fileProperties['type'] = stat.S_IFMT(sbuf.st_mode)
fileProperties['mode'] = stat.S_IMODE(sbuf.st_mode)
fileProperties['mtime'] = sbuf.st_mtime
fileProperties['size'] = sbuf.st_size
if not urlFilePath.startswith("/"):
urlFilePath = "/" + urlFilePath
return render_template('file.html', currentFile=nestedFilePath, fileProperties=fileProperties)
return 'something bad happened'
@app.route('/downloads/<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)
And with the following HTML
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Filebrowser{% endblock %}</h1>
{% endblock %}
{% block content %}
<p>Current file: {{ currentFile }}</p>
<p>
<table>
{% for key, value in fileProperties.items() %}
<tr>
<td>{{ key }}</td>
<td>{{ value }}</td>
</tr>
<tr>
<a href="{{ url_for('downloads', ['image_name']) }}">File</a>
</tr>
{% endfor %}
</table>
</p>
{% endblock %}
I want the download link on that page to work for the {{ currentFile }} can anyone help me out?
Upvotes: 0
Views: 1093
Reputation: 5237
Firstly, the link to the file in your file.html
template should probably go outside the for
loop -- otherwise, the link will appear multiple times which is probably not what you want.
Secondly, based on your /downloads
route, your call to url_for
for the download link doesn't match up. It should be:
<a href="{{ url_for('download', filename=currentFile) }}">File</a>
You need to supply the filename
as an argument so that the flask server can match it to the route & in url_for
, you need to supply the name of the function - which in this case is download
instead of downloads
.
Lastly, your /browser
route prepends the subdirectory to the filename - so when you pass currentFile
to the HTML template, it will contain the directory prefix -- which you will want to strip, otherwise your link wouldn't work. The file download would then work since in your /downloads
route, you prefix the filename
with the directory anyway. Hence, when you render the HTML template, use os.path.basename()
to obtain the filename without the directory, i.e.
return render_template('file.html', currentFile=os.path.basename(nestedFilePath), fileProperties=fileProperties)
Upvotes: 1