Сообщить об ошибке.

Функция send_file() модуля flask в Python

Отправка файла для загрузки/отображения, приложением Flask

Синтаксис:

import flask

flask.send_file(path_or_file, mimetype=None, as_attachment=False, 
                download_name=None, conditional=True, etag=True, 
                last_modified=None, max_age=None)

Параметры:

  • path_or_file - путь к файлу, может быть абсолютный или относительный от текущего рабочего каталога. Тип этого аргумента может быть строкой, PathLike объектом или файловым объектом, открытом в двоичном режиме.
  • mimetype=None - строка, MIME-тип файла. Если не указан, то Flask попытается определить его по расширению файла.
  • as_attachment=False - bool, предлагает браузеру сохранить файл вместо его отображения.
  • download_name=None - строка, имя файла по умолчанию, которое браузеры будут использовать при сохранении файла. По умолчанию используется имя файла, переданное в path_or_file. Этот аргумент необходимо указать, если в path_or_file передан файловый объект.
  • conditional=True - bool, включает условные ответы и ответы диапазона на основе заголовков запросов. Требуется передача пути к файлу и environ.
  • etag=True - bool, вычисляет ETag для файла, который требует передачи пути к файлу. Может быть строкой ETag.
  • last_modified=None - время последнего изменения, указанное в секундах. Если не указан, то Flask попытается обнаружить его по пути к файлу. Тип этого аргумента может быть: datetime.datetime, int, float.
  • max_age=None - int, как долго клиент должен кэшировать файл в секундах. Если установлено, то заголовок Cache-Control будет общедоступным, в противном случае Flask не будет использовать кеширование.

Внимание! В версии Flask 2.0 некоторые аргументы функций flask.send_file() и flask.send_from_directory() были переименованы. Удалено в версии Flask 2.2.0.

  • attachment_filename переименовывается в download_name.
  • cache_timeout переименовывается в max_age.
  • add_etags переименован в etag.
  • filename переименовывается в path_or_file.

Возвращаемое значение:

  • строка, которая указывает путь к файлу для загрузки/отображения.

Описание:

Функция send_file() модуля flask читает файл по пути path_or_file и отправляет его содержимое клиенту для загрузки или отображения.

Первым аргументом может быть путь к файлу или объект, подобный файлу. Пути предпочтительнее в большинстве случаев, потому что модуль Werkzeug может управлять файлом и получать дополнительную информацию из пути. Передача файлового объекта требует, чтобы файл открывался в двоичном режиме (mode='rb'), что в основном полезно при создании файла в памяти с помощью io.BytesIO.

Никогда не передавайте пути к файлам, созданные пользователем. Предполагается, что такой путь является надежным, так как пользователь может создать путь для доступа к файлу, который будет находится за пределами обслуживаемого каталога, например скрипту Python. Для безопасного обслуживания запрошенных пользователем путей, используйте функцию flask.send_from_directory() .

Так же, при обслуживании путей к возвращаемым файлам, во избежании случайного выхода за пределы базового каталога, используйте функцию flask.safe_join(directory, *pathnames), где аргумент directory - доверенный базовый каталог (например app/static), а *pathnames - компоненты ненадежного пути относительно базового каталога. Эта функция безопасно присоединит один или более ненадежных компонентов пути к базовому каталогу.

По умолчанию Flask использует environ['wsgi.file_wrapper'](filelike, block_size) если его устанавливает WSGI-сервер, в противном случае будет используется встроенная обертка Werkzeug.

В качестве альтернативы, если есть HTTP-сервер поддерживающий X-Sendfile (например Nginx), то лучше настроить приложение Flask с параметром конфигурации USE_X_SENDFILE=True, что намного эффективнее использования функции send_file() (чтения файла средствами Python).

Изменено в версии 2.0:

  • download_name заменяет параметр attachment_filename. Если as_attachment=False, то он передается с Content-Disposition: inline.
  • max_age заменяет параметр cache_timeout. Аргумент conditional=True, а max_age по умолчанию не задан.
  • etag заменяет параметр add_etags. Это может быть строка, которую можно использовать вместо генерации.
  • Передача файлового объекта, который наследуется от io.TextIOBase, вызовет ошибку ValueError, а не отправку пустого файла.

Новое в версии 2.0: Реализация функции перенесена в модуль Werkzeug. Теперь это обертка для передачи некоторых специфичных для Flask аргументов.

Примеры отправки файла клиенту при помощи функции send_file():

Отправка файла, расположенного на жестком диске сервера:

@app.route("/get-csv/<path:filename>")
def get_csv(filename):
    # безопасно соединяем базовый каталог и имя файла
    safe_path = safe_join(app.config["CSV_FOLDER"], filename)
    try:
        return send_file(safe_path, as_attachment=True)
    except FileNotFoundError:
        abort(404)

Отправка файла, созданного в оперативной памяти сервера:

@app.route('/test_download')
def test_download():
    row = ['hello', 'world']
    proxy = io.StringIO()
    writer = csv.writer(proxy)
    writer.writerow(row)
    # создаем объект `ByteIO` из объекта `StringIO`
    mem = io.BytesIO()
    mem.write(proxy.getvalue().encode())
    # перевод указателя на начало файла был
    # необходим в 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'
    )