Вы хотите, чтобы ваш Telegram-бот принимал файлы, фото или видео от пользователей - и отвечал им правильно? Это не сложнее, чем настроить кнопку. Но многие делают ошибки, которые ломают бота: файлы не загружаются, бот зависает, или пользователь получает ошибку «Файл не найден». Всё это происходит из-за неправильной обработки медиа. Ниже - пошаговый способ сделать это надежно, без лишних библиотек и костылей.
Как Telegram обрабатывает файлы и медиа
Telegram не отправляет файлы напрямую. Вместо этого он отправляет идентификатор файла - уникальный код, который ссылается на данные, хранящиеся на серверах Telegram. Это значит, что если вы получили файл от пользователя, вы не получаете сам файл, а только его ID. Чтобы скачать его, вы должны запросить его через API Telegram с этим ID.
То же самое с фото и видео. Они приходят как объекты с полями: file_id, file_size, mime_type, и иногда thumb - миниатюра. Если вы не используете file_id, ваш бот не сможет работать с медиа. Это ключевое правило.
Как принять файл от пользователя
Чтобы бот начал принимать файлы, вам нужно настроить обработчик сообщений с типом document. В Python с библиотекой python-telegram-bot это выглядит так:
def handle_document(update, context):
file = update.message.document
file_id = file.file_id
file_name = file.file_name
file_size = file.file_size
# Сохраняем ID файла в базу данных или временно
context.user_data['last_file'] = file_id
update.message.reply_text(f"Файл {file_name} ({file_size} байт) получен. ID: {file_id[:10]}...")
Если пользователь отправит PDF, ZIP или TXT - всё работает одинаково. Telegram не ограничивает типы файлов, если размер не превышает 2 ГБ. Для файлов больше 50 МБ лучше использовать download_file с потоковой загрузкой, чтобы не перегружать память бота.
Как принять фото и видео
Фото и видео - это отдельные типы сообщений. Фото приходят как массив photo, где каждое изображение - это разное разрешение. Вам нужен самый большой вариант - последний элемент в массиве.
def handle_photo(update, context):
photo = update.message.photo[-1] # Самое большое разрешение
file_id = photo.file_id
file_size = photo.file_size
context.user_data['last_photo'] = file_id
update.message.reply_text(f"Фото получено. Размер: {file_size} байт")
Видео - аналогично, но с полем video:
def handle_video(update, context):
video = update.message.video
file_id = video.file_id
duration = video.duration # в секундах
width = video.width
height = video.height
context.user_data['last_video'] = file_id
update.message.reply_text(f"Видео принято. Длительность: {duration} сек, разрешение: {width}x{height}")
Важно: не используйте thumb для загрузки видео. Это только миниатюра. Чтобы получить само видео - всегда берите file_id из поля video.
Как скачать файл с сервера Telegram
Получив file_id, вы можете скачать файл через метод get_file и потом download:
from telegram import Bot
bot = Bot(token="ВАШ_ТОКЕН")
file = bot.get_file(file_id)
file.download("./downloads/" + file.file_path.split("/")[-1])
Это работает для всех типов медиа - документов, фото, видео. Но есть нюанс: file_path - это путь на серверах Telegram, а не на вашем сервере. Вы должны скачать файл вручную. Не пытайтесь использовать file_path как URL - он не работает вне Telegram API.
Для высоконагруженных ботов лучше использовать асинхронную загрузку. Например, с aiogram или httpx с asyncio. Это снижает задержки и предотвращает зависания при одновременной загрузке десятков файлов.
Как отправить файл обратно пользователю
Отправка файла - проще, чем приём. Вы передаёте file_id в метод send_document, send_photo или send_video:
def send_file_back(update, context):
file_id = context.user_data.get('last_file')
if file_id:
update.message.reply_document(file_id)
else:
update.message.reply_text("Сначала отправьте файл.")
То же самое для фото и видео:
update.message.reply_photo(file_id)
update.message.reply_video(file_id)
Вы можете отправлять файлы, которые пользователь отправил вам час назад - Telegram хранит file_id неограниченно долго, пока не удалён сам файл (например, если пользователь удалил его из чата).
Ошибки, которые ломают ботов
Вот три самые частые ошибки, которые приводят к сбоям:
- Использование URL вместо file_id - Telegram не даёт прямых ссылок на файлы. Любая попытка использовать
https://api.telegram.org/file/bot...в браузере или вне API - не сработает. - Загрузка файла в память целиком - если файл 1 ГБ, и вы пытаетесь загрузить его в память Python, бот упадёт. Всегда используйте потоковую загрузку.
- Игнорирование mime-type - если вы отправляете PDF как фото, пользователь получит битый файл. Проверяйте
mime_typeперед обработкой:document.mime_type == "application/pdf".
Ещё одна ловушка: если пользователь отправляет файл с пробелами в названии или кириллицей - имя файла может сломаться при сохранении. Всегда очищайте имена файлов перед записью на диск:
import re
clean_name = re.sub(r'[^a-zA-Z0-9._-]', '_', file_name)
Когда использовать хранилище (Cloud Storage)
Если ваш бот работает с десятками тысяч файлов в день - хранить их на своём сервере неэффективно. Лучше загружать их в облако: Amazon S3, Google Cloud Storage или Yandex Object Storage.
Алгоритм прост:
- Пользователь отправляет файл - бот получает
file_id. - Бот скачивает файл в память (потоком).
- Загружает его в облако.
- Сохраняет ссылку на файл в базу данных вместе с
file_idTelegram. - Отправляет пользователю ссылку на облако.
Это снижает нагрузку на ваш сервер и даёт пользователю постоянную ссылку на файл, даже если он удалит его из чата.
Практический пример: бот для архивации документов
Представьте бота, который принимает сканы паспортов от клиентов банка. Он должен:
- Принимать PDF и JPG
- Проверять размер (не больше 10 МБ)
- Проверять mime-type
- Сохранять файл в S3 под уникальным ID клиента
- Отправлять подтверждение: «Документ получен. Номер заявки: #12345»
Всё это делается за 40 строк кода. Главное - не пытаться «обойти» Telegram API. Он работает стабильно, если вы его используете правильно.
Что делать, если файл не приходит?
Если бот не получает файлы - проверьте:
- Правильно ли вы подписали обработчик на
document,photoиvideo? - Не блокирует ли бот сообщения от незарегистрированных пользователей?
- Не превышает ли файл лимиты Telegram (2 ГБ для документов, 50 МБ для видео без сжатия)?
- Есть ли у бота доступ к интернету? Некоторые хостинги блокируют API Telegram по умолчанию.
Включите логирование. Добавьте строку print(update.message) в обработчик - и вы сразу увидите, приходит ли вообще объект медиа.
Можно ли отправить файл больше 2 ГБ через Telegram-бота?
Нет. Telegram ограничивает размер файла на уровне API - максимум 2 ГБ для документов, 50 МБ для видео без сжатия. Для больших файлов используйте сторонние хранилища (S3, Google Drive) и отправляйте только ссылку через бота.
Почему бот не принимает фото, хотя я настроил обработчик?
Скорее всего, вы используете message.photo, но не указали [-1] для самого большого разрешения. Или вы не подключили обработчик к событию photo - а только к document. Проверьте логи: приходит ли вообще объект photo в update.
Как долго хранятся file_id в Telegram?
File_id остаются действительными бессрочно, пока сам файл не удалён пользователем из чата или не удалён Telegram из-за нарушения правил. Даже если вы перезапустили бота - file_id сохраняются. Но если пользователь удалил файл из своего чата - file_id становится недействительным.
Можно ли отправить видео без сжатия?
Да, если пользователь отправит видео как «файл» (не как видео), Telegram не будет его сжимать. Но если он отправит через кнопку «Видео», Telegram автоматически сожмёт его до 50 МБ. Чтобы избежать сжатия - пользователь должен выбрать «Отправить как файл» в клиенте Telegram.
Как проверить, что файл загружен полностью?
Сравните размер файла на сервере Telegram (file.file_size) с размером скачанного файла на вашем сервере. Если они совпадают - загрузка прошла успешно. Для больших файлов используйте хеш-сумму (SHA-256) для проверки целостности.