在 Pythonanywhere 上的烧瓶中替代 send_file()?
Posted
技术标签:
【中文标题】在 Pythonanywhere 上的烧瓶中替代 send_file()?【英文标题】:Alternative of send_file() in flask on Pythonanywhere? 【发布时间】:2018-10-09 19:03:41 【问题描述】:我是 python 新手,还在学习。我在 pythonanwhere 上创建了一个小的 python 3.6 Flask webapp,发现 send_file() 在 pythonanywhere 服务器上不起作用。我正在积极寻找直接在用户机器上下载 excel 文件的替代方法。我也试过 Response 但它没有提供所需的输出。 我在网上看了很多,发现如果我们在下面设置 send_file 工作正常
wsgi-disable-file-wrapper = True
但是,我不知道在哪里设置它,因为我找不到可以更新此行的 uWsgi.ini 文件。
以下是我尝试过的方法,但都失败了,请帮忙
SEND_FILE() 配置: ->>> 未运行..
output = BytesIO()
writer = pd.ExcelWriter(output, engine='xlsxwriter')
workbook = writer.book
output.seek(0)
return send_file(output,attachment_filename="testing.xlsx",as_attachment=True)
输出错误:
return environ.get('wsgi.file_wrapper', FileWrapper)(file, buffer_size)
SystemError: <built-in function uwsgi_sendfile> returned a result with an error set
带有响应配置:
writer = pd.ExcelWriter("abc.xlsx", engine='xlsxwriter')
return Response(writer,mimetype="text/csv",headers="Content-disposition":"attachment; filename=myplot.csv")
输出错误:
Error running WSGI application
TypeError: '_XlsxWriter' object is not iterable
File "/home/hridesh1987/.virtualenvs/myproject/lib/python3.6/site-packages/werkzeug/wsgi.py", line 870, in __next__return self._next()
File "/home/hridesh1987/.virtualenvs/myproject/lib/python3.6/site-packages/werkzeug/wrappers.py", line 83, in _iter_encoded
for item in iterable:
【问题讨论】:
您是如何发现 send_file 在 PythonAnywhere 上不起作用的?据我所知,它应该有效吗? @conrad 见pythonanywhere.com/forums/topic/8612 【参考方案1】:我在 PythonAnywhere 论坛上提出了同样的问题,他们给了我this response。感谢 PythonAnywhere 工作人员的“格伦”。
复制粘贴:
from io import BytesIO
from flask import Flask, Response
from werkzeug import FileWrapper
app = Flask(__name__)
@app.route('/')
def hello_world():
b = BytesIO(b"blah blah blah")
w = FileWrapper(b)
return Response(w, mimetype="text/plain", direct_passthrough=True)
我根据自己的使用情况稍微调整了它。我通过Content-Disposition
标头设置文件名。我还必须调整 FileWrapper
导入,而 data
在我的代码中已经是 BytesIO
对象:
from flask import Response
from werkzeug.wsgi import FileWrapper
def send_excel_file(data, filename):
# See: https://www.pythonanywhere.com/forums/topic/13570/
file_wrapper = FileWrapper(data)
headers =
'Content-Disposition': 'attachment; filename=""'.format(filename)
response = Response(file_wrapper,
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
direct_passthrough=True,
headers=headers)
return response
【讨论】:
【参考方案2】:从 Mat 的回答中提到的论坛,我证实:
[
send_file()
] 不起作用,因为 uWSGI 文件包装器不支持类文件对象,只支持真实文件
...但是应用 Mat 的解决方案仍然会引发 ValueError: I/O operation on closed file。即使使用 FileWrapper 类。
这种方式更简单:如果您使用基于io
的文件指针,例如。 io.StringIO()
您必须改用 Response()
。不是使用 fp 而是直接发送内容。根据您的代码:
with BytesIO() as output:
writer = pd.ExcelWriter(output, engine='xlsxwriter')
output.seek(0)
headers = "Content-disposition": "attachment; filename=testing.xlsx"
mimetype = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
return Response(output.read(), mimetype=mimetype, headers=headers)
【讨论】:
`workbook = writer.book` 是做什么的,貌似没有被使用 你是对的,但那部分在他的代码中。我试图不改变他的例子,但现在它已经修复了。重要的部分是Response()
的变化,读取io.BytesIO()
对象,所以我没有传递指针,而是传递了bytes()。以上是关于在 Pythonanywhere 上的烧瓶中替代 send_file()?的主要内容,如果未能解决你的问题,请参考以下文章
在 pythonanywhere.com 上部署烧瓶站点/应用程序
尝试使用 PythonAnyWhere 部署 Web Flask 应用程序时出现 WSGI 错误