在 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 错误

dotenv 模块未找到错误 pythonanywhere

如何在烧瓶中记录信息? [复制]

如何通过 Javascript 在 PythonAnywhere 上的 OpenCV 中访问网络摄像头?

PythonAnywhere 上的 JSONDecodeError