【问题标题】:Python Flask send_file StringIO blank filesPython Flask send_file StringIO 空白文件
【发布时间】: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 但是你不能对关闭的文件进行操作。

标签: python flask stringio


【解决方案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"。另见stackoverflow.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文件

参考文献

合十礼?

【讨论】:

    【解决方案4】:

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

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

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

    谢谢

    【讨论】:

      猜你喜欢
      • 2023-01-27
      • 1970-01-01
      • 2021-05-18
      • 2017-09-24
      • 2013-06-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多