Python Flask send_file StringIO 空白文件

Posted

技术标签:

【中文标题】Python Flask send_file StringIO 空白文件【英文标题】:Python Flask send_file StringIO blank files 【发布时间】:2016-06-13 03:07:29 【问题描述】:

我正在使用 python 3.5 和flask 0.10.1 并且喜欢它,但是在使用 send_file 时遇到了一些问题。我最终想要处理一个 pandas 数据帧(来自表单数据,在本示例中未使用,但将来需要)并将其发送为 csv 下载(没有临时文件)。我见过的最好的实现方法是 StringIO。

这是我尝试使用的代码:

@app.route('/test_download', methods = ['POST'])
def test_download():
    buffer = StringIO()
    buffer.write('Just some letters.')
    buffer.seek(0)
    return send_file(buffer, as_attachment = True,\
    attachment_filename = 'a_file.txt', mimetype = 'text/csv')

使用正确名称下载文件,但该文件完全为空白。

有什么想法吗?编码问题?这在其他地方得到了回答吗? 谢谢!

【问题讨论】:

@bernie 但是你不能对关闭的文件进行操作。 【参考方案1】:

这里的问题是,在 Python 3 中,您需要将 StringIOcsv.write 一起使用,而 send_file 需要 BytesIO,因此您必须同时使用两者。

@app.route('/test_download')
def test_download():
    row = ['hello', 'world']
    proxy = io.StringIO()
    
    writer = csv.writer(proxy)
    writer.writerow(row)
    
    # Creating the byteIO object from the StringIO Object
    mem = io.BytesIO()
    mem.write(proxy.getvalue().encode())
    # seeking was necessary. Python 3.5.2, Flask 0.12.2
    mem.seek(0)
    proxy.close()

    return send_file(
        mem,
        as_attachment=True,
        attachment_filename='test.csv',
        mimetype='text/csv'
    )

【讨论】:

这应该是公认的答案,因为它在使用 send_file() 方法导出/下载 CSV 文件的意义上更通用。 在编码中我添加了"utf-8-sig",或者你可能想要"utf-8"。另见***.com/questions/2223882/…【参考方案2】:

我猜你应该写字节。

from io import BytesIO    

from flask import Flask, send_file


app = Flask(__name__)


@app.route('/test_download', methods=['POST'])
def test_download():
    # Use BytesIO instead of StringIO here.
    buffer = BytesIO()
    buffer.write(b'jJust some letters.')
    # Or you can encode it to bytes.
    # buffer.write('Just some letters.'.encode('utf-8'))
    buffer.seek(0)
    return send_file(buffer, as_attachment=True,
                     attachment_filename='a_file.txt',
                     mimetype='text/csv')


if __name__ == '__main__':
    app.run(debug=True)

【讨论】:

是的,这行得通——我刚刚了解到 python 3 上的烧瓶不适用于 StringIO。跟进问题-您知道将熊猫数据帧转换为字节 csv 以供下载的方法吗? @DanielHitchcock 嗨,您应该提供一个最小、完整和可验证的示例,以便我可以重现这个问题(比如这个问题,但是使用 pandas 数据框示例),我对 pandas 并不熟悉所以我目前的答案是否定的。如有必要,您可以提出其他问题。 关键部分是“buffer.seek(0)” - 我遇到了来自 pandas 的 excel 文件的问题,并通过这一行解决了【参考方案3】:

make_response

为了让 Flask 将 csv 文件下载给用户,我们将 csv 字符串传递给 make_response 函数,该函数返回一个 Response 对象。 然后我们添加一个 Header 告诉浏览器接受文件作为下载。 Mimetype 也必须设置为 text/csv,以便让网络浏览器将其保存在 html 文档以外的其他文件中。
from flask import Flask, make_response  
app = Flask(__name__)

@app.route('/test_download', methods=['POST'])
def test_download():
    with StringIO() as buffer:
        # forming a StringIO object  
        buffer = StringIO()
        buffer.write('Just some letters.')
        # forming a Response object with Headers to return from flask 
        response = make_response(buffer.getvalue())
        response.headers['Content-Disposition'] = 'attachment; filename=namaste.csv'
        response.mimetype = 'text/csv'
        # return the Response object
        return response

P.S.最好使用python内置的csv库处理csv文件

参考文献

https://matthewmoisen.com/blog/how-to-download-a-csv-file-in-flask/ https://www.geeksforgeeks.org/stringio-module-in-python/ https://docs.python.org/3/library/csv.html

合十礼?

【讨论】:

【参考方案4】:

如果有人在 Flask 中使用 python 2.7 并通过导入模块 StringIO 得到错误。这篇文章可以帮助你解决你的问题。

如果您正在导入 String IO 模块,您可以使用以下命令更改导入语法:from io import StringIO 而不是 from StringIO import StringIO

如果您使用图像或其他一些资源,您也可以使用 from io import BytesIO

谢谢

【讨论】:

以上是关于Python Flask send_file StringIO 空白文件的主要内容,如果未能解决你的问题,请参考以下文章

使用Python Flask中的send_file发送视频时移动设备发生错误http://mattspitz.me/2013/11/20/serving-authenticated-media-wit

尽管有 200 条消息,flask send_file 仍然失败 [重复]

Flask send_file request

flask send_file使用

来自 Flask send_file 的 Zip 文件无效

Flask send_file 返回 200 OK 但不发送文件