在Pythonanywhere上烧瓶中的send_file()的替代方案?

时间:2018-04-29 14:36:02

标签: python python-3.x flask pythonanywhere x-sendfile

我是python的新手,还在学习。我在pythonanwhere上创建了一个小的python 3.6 Flask webapp,发现send_file()不能在pythonanywhere服务器上运行。我正在积极寻找直接在用户计算机上下载excel文件的替代方案。我也尝试了响应,但它没有提供所需的输出。 我在线阅读了很多关于它的信息,发现如果我们设置在

之下,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:

2 个答案:

答案 0 :(得分:2)

我在PythonAnywhere论坛上提出了同样的问题,他们给了我this response。感谢PythonAnywhere员工的“ glenn”。

复制粘贴:

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

答案 1 :(得分:1)

在Mat的答案中提到的论坛中,我验证了这一点:

[{send_file()]不起作用,因为uWSGI文件包装器不支持类似文件的对象,仅支持真实文件

...但是应用Mat的解决方案仍然会向我抛出 ValueError:对已关闭文件的I / O操作。即使使用FileWrapper类。

这种方式更简单:如果您使用基于io的file_pointer,例如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)