Python Flask send_file StringIO пустые файлы

Я использую 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')

Загрузка файла с соответствующим именем, однако файл полностью пуст.

Любые идеи? Проблемы с кодировкой? Получили ли это ответ в другом месте? Спасибо!

Ответ 1

Проблема здесь в том, что в Python 3 вам нужно использовать StringIO с csv.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('utf-8'))
    # 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'
    )

Ответ 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)

Ответ 3

если кто-то использует python 2.7 с Flask и получил ошибку об модуле StringIO, импортировав его. Этот пост может помочь вам решить вашу проблему.

Если вы импортируете модуль String IO, вы можете просто изменить синтаксис импорта, используя это: из io import StringIO вместо из StringIO import StringIO.

Вы также можете использовать из io import BytesIO, если вы используете изображение или некоторые другие ресурсы.

Спасибо