什么';这是考虑在apache上使用mod_wsgi提供Flask应用程序的文件路径的正确方法

什么';这是考虑在apache上使用mod_wsgi提供Flask应用程序的文件路径的正确方法,flask,apache2,Flask,Apache2,我正试图允许用户从我的flask应用程序下载csv文件,但这是一种从运行Apache2的Ubuntu18服务器下载文件的方式 import flask import os from io import BytesIO basedir = os.path.abspath(os.path.dirname(__file__)) app = flask.Flask(__name__) app.config["DEBUG"] = True @app.route('/<string:report

我正试图允许用户从我的flask应用程序下载csv文件,但这是一种从运行Apache2的Ubuntu18服务器下载文件的方式

import flask
import os
from io import BytesIO

basedir = os.path.abspath(os.path.dirname(__file__))

app = flask.Flask(__name__)
app.config["DEBUG"] = True

@app.route('/<string:report>/<string:action>', methods=['GET'])
def report(report,action):
    if action == 'download': 
        files = os.listdir(os.path.join(basedir, f'static/reports/{report}'))
        filepath = url_for(f'static/reports/{report}/{files[-1]}')
        output = BytesIO()
        with open(filepath, 'rb') as f:
            data = f.read()
        output.write(data)
        output.seek(0)
        return send_file(output,attachment_filename=files[-1], as_attachment=True)
我也尝试过在static下为我的reports文件夹创建别名,但仍然得到相同的结果


我有什么明显的遗漏吗

您的错误是使用
url\u for()
生成路径
url\u for()
生成url路径,而不是文件系统路径。无法使用结果打开本地文件
url\u for()
用于将浏览器发送到正确的位置

您正在从标准
静态路径提供文件。只需找出烧瓶的位置,
app
/
current\u app
对象

您还希望使用直接为文件提供服务。这里不需要首先将数据加载到
BytesIO()
对象中
send\u from_directory
接受相对路径作为第二个参数

这应该起作用:

@app.route('/<string:report>/<string:action>', methods=['GET'])
def report(report, action):
    if action == 'download': 
        files = os.listdir(os.path.join(app.static_folder, 'reports', report))
        filename = files[-1]
        filepath = os.path.join('reports', report, filename)
        return send_from_directory(app.static_folder, filepath, as_attachment=True)
@app.route('/',方法=['GET'])
def报告(报告、行动):
如果操作==“下载”:
files=os.listdir(os.path.join(app.static_文件夹,'reports',report))
filename=文件[-1]
filepath=os.path.join('reports',report,filename)
从_目录返回发送_(app.static_文件夹,filepath,as_attachment=True)
我省略了
附件\u filename
,因为默认设置已经是使用所提供文件的文件名


您可能需要重新考虑
文件[-1]
策略
os.listdir()
以任意顺序生成文件(操作系统决定的任何顺序都是最方便的)。如果您希望它是最近创建或修改的文件,则必须先进行自己的排序。

为什么要将数据读入
BytesIO()
对象
send_file()
将直接接受
filepath
,并更有效地引导文件。或者使用
send_from_directory()
,它接受目录和文件名。谢谢!
static\u文件夹
的解释非常有用。
@app.route('/<string:report>/<string:action>', methods=['GET'])
def report(report, action):
    if action == 'download': 
        files = os.listdir(os.path.join(app.static_folder, 'reports', report))
        filename = files[-1]
        filepath = os.path.join('reports', report, filename)
        return send_from_directory(app.static_folder, filepath, as_attachment=True)