【问题标题】:Alternative of send_file() in flask on Pythonanywhere?在 Pythonanywhere 上的烧瓶中替代 send_file()?
【发布时间】: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:

【问题讨论】:

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


【解决方案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()。
    猜你喜欢
    • 2014-12-09
    • 2019-05-13
    • 2015-10-11
    • 2019-08-19
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 2016-01-08
    • 1970-01-01
    相关资源
    最近更新 更多