Как в Flask отправить изображение в ответе на HTTP-запрос?

«Как в Flask отправить изображение в ответе на HTTP-запрос?» — вопрос из категории Сети, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для отправки файлов, включая изображения, в Flask используется функция send_file. Она автоматически устанавливает необходимые HTTP-заголовки, такие как Content-Type, на основе MIME-типа файла.

1. Отправка статического файла

Это самый простой случай, когда изображение уже существует на диске.

from flask import Flask, send_file

app = Flask(__name__)

@app.route('/get-image')
def get_image():
    # Путь к файлу изображения
    filename = 'images/my_cat.jpg'
    try:
        # Отправляем файл, указывая его MIME-тип
        return send_file(filename, mimetype='image/jpeg')
    except FileNotFoundError:
        return "File not found", 404

Почему это работает? send_file читает файл и передает его содержимое в теле HTTP-ответа, а заголовок Content-Type: image/jpeg сообщает браузеру, что нужно отобразить полученные данные как изображение.

2. Динамическая генерация и отправка изображения

Изображение можно сгенерировать на лету, например, с помощью библиотеки Pillow, и отправить его без сохранения на диск. Для этого используется объект io.BytesIO, который ведет себя как файл в памяти.

import io
from flask import Flask, send_file
from PIL import Image, ImageDraw

app = Flask(__name__)

@app.route('/generate-image')
def generate_image():
    # Создаем буфер в памяти
    img_io = io.BytesIO()

    # Генерируем изображение 100x100 с красным квадратом
    img = Image.new('RGB', (100, 100), 'blue')
    draw = ImageDraw.Draw(img)
    draw.rectangle([20, 20, 80, 80], fill='red')

    # Сохраняем изображение в буфер в формате PNG
    img.save(img_io, 'PNG')
    # Перемещаем "курсор" в начало буфера
    img_io.seek(0)

    # Отправляем буфер как файл
    return send_file(img_io, mimetype='image/png')

Рекомендации для production

В production-среде статические файлы (CSS, JS, изображения) не рекомендуется отдавать через Flask, так как это неэффективно. Вместо этого следует настроить веб-сервер (например, Nginx или Apache) для прямой отдачи статики. Это освобождает ресурсы Python-приложения для обработки динамических запросов.