我有一个烧瓶应用程序,它接收用户/投资组合 id 表单,然后创建一个显示用户数据、信息、图表等的页面。我正在尝试为每个用户投资组合/工具插入一个下载 CSV 数据链接/按钮.
我正在通过烧瓶会议来做到这一点。由于 CSV 数据超过了 cookie 限制,我需要使用特殊会话。直到现在我尝试使用 Redis 都没有成功(但它可能是一个选项),所以我正在使用文件系统 Flask 会话,它给出了错误OSError: [Errno 36] File name too long。
这是我的代码的简化:
应用程序.py
from flask import Flask, render_template, redirect, request, session, send_file
from flask_wtf import FlaskForm
from flask_session import Session #this module has upper and lower case versions - I'm using lower
from wtforms import StringField, SelectField, SubmitField, validators
from wtforms.validators import DataRequired
from flask_bootstrap import Bootstrap
#import my modules
app = Flask(__name__)
SESSION_TYPE = 'filesystem' #redis #filesystem
app.config.from_object(__name__)
Session(app)
Bootstrap(app)
app.config.from_mapping(SECRET_KEY=.....)
...
#home route
@app.route('/', methods=['GET', 'POST'])
def home():
form = DataForm(request.form)
if request.method == 'POST' and form.validate_on_submit():
data_id = request.form['data_id']
target= request.form['target']
return redirect(f"/data/{target}/{data_id}")
return render_template('home.html', form=form)
#route which receives user/portfolio id, gets data and creates display page
@app.route('/data/<target>/<data_id>')
def customeranalysis(target, data_id):
data_id = procedures.handle_id(data_id)
if target == 'user':
user_infos, user_names, graphs, annual_tables, twelve_months_tables, monthly_tables, csvs = procedures.user_info(data_id)
for i in range(len(user_names)):
session[user_names[i]] = csvs[i]
return render_template('data_display_page.html',
user_id=data_id,
dfs=user_infos,
names=user_names,
graphs=graphs,
annual_tables=annual_tables,
twelve_months_tables=twelve_months_tables,
monthly_tables=monthly_tables)
if target == 'portfolio':
#same as previous if, a little different
#route for the download page, to which the download link in previous route points
@app.route("/get_csv/<filename>", methods=['GET', 'POST'])
def get_csv(filename):
df = session[filename]
try:
return send_file(df,
as_attachment=True,
attachment_filename='dados.csv'
)
except FileNotFoundError:
abort(404)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
因此,在我的 data_display_page.html 模板页面中,我有以下代码,它创建了下载链接:
data_display_page.html
{% for i in range(names| length) %}
...
<a href="{{url_for('get_csv', filename=names[i])}}" id="download" class="btn btn-outline-info">Download data</a>
...
当我运行 docker-compose 时,一切运行良好,但是当我单击下载加载链接并被重定向时,我在浏览器和控制台上收到内部服务器错误,我得到以下信息:
cmd:码头工人撰写错误
web_1 | 172.27.0.1 - - [15/Apr/2021 18:34:15] "GET /data/portfolio/portfolio_api_id HTTP/1.1" 200 -
web_1 | [2021-04-15 18:34:47,836] ERROR in app: Exception on /get_csv/portfolio_name[GET]
web_1 | Traceback (most recent call last):
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
web_1 | response = self.full_dispatch_request()
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
web_1 | rv = self.handle_user_exception(e)
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
web_1 | reraise(exc_type, exc_value, tb)
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
web_1 | raise value
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
web_1 | rv = self.dispatch_request()
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
web_1 | return self.view_functions[rule.endpoint](**req.view_args)
web_1 | File "/code/app.py", line 86, in get_csv
web_1 | return send_file(df,
web_1 | File "/usr/local/lib/python3.8/site-packages/flask/helpers.py", line 629, in send_file
web_1 | file = open(filename, "rb")
web_1 | OSError: [Errno 36] File name too long: #Long string which is actually not the CSV's name, but the CSV string itself
不知何故,它认为文件名是整个 CSV 字符串,包含所有列和行等。