Search code examples
pythonflaskstringio

Python Flask send_file StringIO blank files


I want to process a Pandas dataframe and send it to download as a CSV without a temp file. The best way to accomplish this I've seen is to use StringIO. Using the code below, a file downloads with the proper name, however the file is completely blank, and no error is shown. Why doesn't the file contain data?

@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,
        download_name='a_file.txt',
        mimetype='text/csv'
    )

Solution

  • 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.