Python Flask send_file StringIO blank files
make_response
- To get Flask to download a csv file to the user, we pass a csv string to the
make_response
function, which returns aResponse
object. - Then we add a Header which tells the browser to accept the file as a download.
- The Mimetype also must be set to
text/csv
in order to get the web browser to save it in something other than an html document.
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. It is preferred to use python's built-in
csv
library to deal withcsv
files
References
- 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
Namaste ð
Use BytesIO
to write bytes.
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'Just 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,
download_name='a_file.txt',
mimetype='text/csv'
)
Prior to Flask 2.0, download_name
was called attachment_filename
.
The issue here is that in Python 3 you need to use StringIO
with csv.write
and send_file
requires BytesIO
, so you have to do both.
@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,
download_name='test.csv',
mimetype='text/csv'
)
Prior to Flask 2.0, download_name
was called attachment_filename
.