python - flask send_from_directory within a file representation
问题描述
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?
解决方案
首先,file.html
模板中文件的链接可能应该在循环之外for
——否则,链接会出现多次,这可能不是你想要的。
其次,根据您的/downloads
路线,您url_for
对下载链接的调用不匹配。它应该是:
<a href="{{ url_for('download', filename=currentFile) }}">File</a>
您需要提供filename
作为参数,以便烧瓶服务器可以将其与路由 & in 匹配url_for
,您需要提供函数的名称- 在这种情况下是download
而不是downloads
.
最后,您的/browser
路由将子目录添加到文件名之前 - 因此当您传递currentFile
给 HTML 模板时,它将包含目录前缀 - 您将要删除它,否则您的链接将无法正常工作。然后文件下载将起作用,因为在您的/downloads
路线中,filename
无论如何您都要在目录前面加上前缀。因此,当您渲染 HTML 模板时,使用os.path.basename()
获取没有目录的文件名,即
return render_template('file.html', currentFile=os.path.basename(nestedFilePath), fileProperties=fileProperties)
推荐阅读
- c - 对平方数字求和时是否需要明确处理负数或零?
- r - 将复制的数据移动到 R 中的下一列
- termux - Termux 在命令上返回错误:from pymongo import MongoClient
- python - 无法将列表转换为整数并遍历列表
- machine-learning - LightGBM 对缺失标签的支持是什么
- javascript - 为什么我选中的单选框值与传递的值不同?
- visual-studio-code - 为单个日志文件创建 C++ 问题匹配器?
- c# - 库的子文件夹中的 CSOM 更新文件文档元数据。找不到错误文件
- javascript - 单击两次以使用 JavaScript 填充两个隐藏字段?
- r - 如何使用 gganimate 在 R 中为 geom_polygon 设置动画?