Flask.send_file sends blank files when using io.StringIO in Python 3. There is a warning that this is wrong but the response code is still 200 but with a blank file.
Testing this behavior with a test_client will however still result in output. Which doesn't really make sense.
Related Info:
https://stackoverflow.com/questions/35710361/python-flask-send-file-stringio-blank-files
Expected Behavior
Flask.send_file should accept an io.StringIO file object and send it to the browser properly
Flask.send_file should 500 on the the request instead of a blank file
app.test_client shouldn't have data in this setup
Test Case:
Run in Python 3
import sys
if sys.version_info >= (3, 0):
from io import StringIO
else:
from StringIO import StringIO
from flask import Flask, send_file
import csv
app = Flask(__name__)
@app.route('/')
def hello_world():
temp = StringIO()
writer = csv.writer(temp)
header = ['test', 'test']
writer.writerow(header)
temp.seek(0)
return send_file(
temp,
as_attachment=True,
cache_timeout=-1,
attachment_filename="test.csv"
)
app.test_client()
with app.test_client() as c:
rv = c.get('/')
print(rv.data)
app.run(debug=True, threaded=True, host="127.0.0.1", port=4000)
❯ python3 test_case.py
b'test,test\r\n'
* Serving Flask app "test_case" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:4000/ (Press CTRL+C to quit)
* Restarting with stat
b'test,test\r\n'
* Debugger is active!
* Debugger PIN: 881-854-930
127.0.0.1 - - [10/Sep/2019 02:15:54] "GET / HTTP/1.1" 200 -
Error on request:
Traceback (most recent call last):
File "/Users/kchung/.virtualenvs/ctfd3/lib/python3.7/site-packages/werkzeug/serving.py", line 303, in run_wsgi
execute(self.server.app)
File "/Users/kchung/.virtualenvs/ctfd3/lib/python3.7/site-packages/werkzeug/serving.py", line 294, in execute
write(data)
File "/Users/kchung/.virtualenvs/ctfd3/lib/python3.7/site-packages/werkzeug/serving.py", line 274, in write
assert isinstance(data, bytes), "applications must write bytes"
AssertionError: applications must write bytes
❯ curl -vvv http://localhost:4000
* Rebuilt URL to: http://localhost:4000/
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 4000 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4000 (#0)
> GET / HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.54.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Disposition: attachment; filename=test.csv
< Content-Type: text/csv; charset=utf-8
< Cache-Control: public, max-age=-1
< Expires: Tue, 10 Sep 2019 06:29:28 GMT
< Connection: close
< Server: Werkzeug/0.15.6 Python/3.7.4
< Date: Tue, 10 Sep 2019 06:29:29 GMT
<
* Closing connection 0
Actual Behavior
- With Python 3 Hitting the endpoint in a browser results in an empty file but in the test_client there is a data response.
Environment
- Python version: 3.7.4
- Flask version: 1.1.1
- Werkzeug version: 0.15.3
Flask.send_filesends blank files when usingio.StringIOin Python 3. There is a warning that this is wrong but the response code is still 200 but with a blank file.Testing this behavior with a test_client will however still result in output. Which doesn't really make sense.
Related Info:
https://stackoverflow.com/questions/35710361/python-flask-send-file-stringio-blank-files
Expected Behavior
Flask.send_fileshould accept anio.StringIOfile object and send it to the browser properlyFlask.send_fileshould 500 on the the request instead of a blank fileapp.test_clientshouldn't have data in this setupTest Case:
Run in Python 3
Actual Behavior
Environment