This is an issue when flask.send_file() is called with a file-like object without providing either the mimetype or
download_name parameter.
Flask’s send_file() function needs to determine the content type for HTTP responses. When you pass a file-like object, such as an open
file handle, BytesIO, or StringIO, Flask cannot infer the content type automatically. Providing either mimetype
or download_name resolves the issue. When download_name is provided, Flask can infer the mimetype via the file
extension.
Without the mimetype parameter, Flask doesn’t know what Content-Type header to set for the response. Without
download_name, Flask cannot set the Content-Disposition header properly for downloads.
When Flask encounters this situation, it raises a ValueError with a message indicating that it cannot determine the content type. This
causes your application to crash with a 500 Internal Server Error, creating a poor user experience.
The application will crash with a ValueError when the endpoint is accessed, resulting in a 500 Internal Server Error response. This
breaks the file download functionality and creates a poor user experience.
Add the mimetype parameter to specify the content type of the file being sent.
from flask import send_file
def download_file():
file_obj = open('data.txt', 'rb')
return send_file(file_obj) # Noncompliant
from flask import send_file
def download_file():
file_obj = open('data.txt', 'rb')
return send_file(file_obj, mimetype='text/plain')
Add the download_name parameter to specify the filename for downloads. This is especially useful for in-memory file objects. For Flask
versions prior to 2.0, use attachment_filename instead.
from flask import send_file
from io import BytesIO
def download_csv():
csv_data = BytesIO(b'name,age\nJohn,30')
return send_file(csv_data) # Noncompliant
from flask import send_file
from io import BytesIO
def download_csv():
csv_data = BytesIO(b'name,age\nJohn,30')
return send_file(csv_data, download_name='data.csv', as_attachment=True)
You can provide both parameters for complete control over the response headers.
from flask import send_file
from io import StringIO
def download_log():
log_data = StringIO('INFO: Application started')
return send_file(log_data) # Noncompliant
from flask import send_file
from io import StringIO
def download_log():
log_data = StringIO('INFO: Application started')
return send_file(log_data, mimetype='text/plain', download_name='app.log')