Appearance
Aiogram 3: Отправка файлов
https://habr.com/ru/articles/822061/
Для понимания работы с медиа сообщениями, так как для текстовых сообщений, используются схожие методы с небольшими отличиями, зависящими от типа сообщения. Например, для работы с фото используются методы answer_photo
, reply_photo
, send_photo
, а для документов — answer_document
, reply_document
, send_document
и так далее.
Также важно помнить, что правила, применяемые к текстовым сообщениям, распространяются и на медиа сообщения, за исключением того, что в медиа отсутствует объект текста message.text
. Там, где это возможно (например, при добавлении подписи к фото или видео), используется элемент caption
.
Методы для редактирования текста в медиа заменяются на методы для редактирования подписей edit_caption
, а для замены медиа контента используется метод edit_media
. Замена клавиатур для всех поддерживающих их медиа сообщений ничем не отличается от замены клавиатур в текстовых сообщениях.
Типы медиа контента и их особенности:
- Фото
- Видео
- Видео сообщения
- Аудио
- Аудио сообщения
- Отправка медиагруппы
- Отправка анимаций, стикеров и прочего
- Разберем имитацию действий
Отправка файлов
Независимо от типа медиафайлов отправка может быть осуществлена следующим способом:
- Физическая отправка файлов (байтов) через
FSInputFile
- Через
ID
файла (неважно это фото, видео, аудио и так далее) - Через
URL
ссылку (формат поддерживается для большинства типов файлов, важно чтоб ссылка вела именно на медиа файл, а не на страницу, где этот файл лежит).
Давайте приступим к разбору. Сейчас мы будем рассматривать тему отправки файлов и, чтобы было проще демонстрировать этот процесс, подготовил папку с именем all_media
в корне проекта бота. В нем следующие типы файлов:
- Несколько обычных видео
- Квадратное видео небольших размеров (для отправки «кругляша»)
- Пару небольших аудио файлов
- Несколько фотографий разного размера
Также подготовил несколько ссылок на медиаконтент (на фото). Подготовьте медиа для тестирования отправок. Как минимум это будет интереснее.
В корневом файле create_bot.py
импортирую os
и прописываю путь к файлу таким образом:
python
all_media_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'all_media')
Далее просто буду импортировать этот путь (переменную) в хендлерах бота.
Я настоятельно рекомендую вам также указывать путь к папкам и файлам таким образом. Данная структура позволит вам не беспокоиться о доступах к файлам (путях) когда вы будете перевозить своего бота с Windows на Ubuntu, например (пути к файлам по-разному записываются).
Далее, для указания конкретного файла можно будет использовать такую запись:
python
photo_file = os.path.join(all_media_dir, 'photo.jpg')
Физическая отправка файлов (байтов) через FSInputFile
Этот метод позволяет загружать файлы с вашего локального устройства (сервер, локальный компьютер). Для использования этого метода сначала нужно импортировать:
python
from aiogram.types import Message, FSInputFile
Теперь отправим аудио сообщение и просто аудио. Для этого предлагаю завязывать будущую отправку файлов на специальные команды: /send_audio
, /send_voice
и так далее.
Пишем хендлер для отправки аудио сообщения:
python
@start_router.message(Command('send_audio'))
async def cmd_start(message: Message, state: FSMContext):
audio_file = FSInputFile(path=os.path.join(all_media_dir, 'new_message_tone.mp3'))
await message.answer_audio(audio=audio_file)
Если не хотите чтоб бот отправлял настоящее имя файла, то передавайте аргумент filename
в FSInputFile
с указанием имени файла.
Стоит обратить внимание, как мы передали путь к файлу. По этому же принципу можно передавать путь к любому медиа файлу (документ, фото, видео, анимация и прочее).
Далее, как я и говорил выше, метод для ответа на команду не особо отличается от аналогичного у текста. Единственное, что обязательно нужно передать путь к аудио файлу, ссылку на него (именно прямая ссылка на загрузку) или ID
файла (об этом чуть дальше).
Вместе с аудио сообщением можно передать клавиатуру (инлайн или текстовую) и можно добавить описание (обычное или отформатированное) через caption
. Почему с текстовыми клавиатурами нужно быть осторожным вы узнаете далее, а пока пример:
python
@start_router.message(Command('send_audio'))
async def cmd_start(message: Message, state: FSMContext):
audio_file = FSInputFile(path=os.path.join(all_media_dir, 'new_message_tone.mp3'))
msg_id = await message.answer_audio(audio=audio_file, reply_markup=main_kb(message.from_user.id),
caption='Моя <u>отформатированная</u> подпись к <b>файлу</b>')
print(msg_id.message_id)
На примере вывел print(msg_id.message_id)
, это не единственное, что нас может заинтересовать в этом объекте. После отправки файла мы можем перехватить его file_id
. Это очень полезно и важно.
Вывод в консоль msg_id.audio.file_id
:
shell
CQACAgIAAxkDAAIBu2ZsgniQlznR1VxJqbHB2pwjKuq2AALmSAACGKhoS96YeMoflmQgNQQ
Если боту будут отправляться медиа сообщения (фото, видео, аудио и так далее) или он их отправит сам – у вас будет возможность перехватить file_id
этих медиа файлов.
По сути, ID
файла это некая ссылка на серверах Telegram
, благодаря которой у бота, владельцем этого файла, появляется возможность повторно отправлять файлы, но уже не физически, а при помощи отправки ссылки на этот файл.
Давайте попробуем выполнить отправку этого аудио через идентификатор.
python
@start_router.message(Command('send_audio'))
async def cmd_start(message: Message, state: FSMContext):
# audio_file = FSInputFile(path=os.path.join(all_media_dir, 'new_message_tone.mp3'))
audio_id = 'CQACAgIAAxkDAAIBu2ZsgniQlznR1VxJqbHB2pwjKuq2AALmSAACGKhoS96YeMoflmQgNQQ'
msg_id = await message.answer_audio(audio=audio_id, reply_markup=main_kb(message.from_user.id),
caption='Моя <u>отформатированная</u> подпись к <b>файлу</b>')
Смотрим и видим, что бот смог отправить аудио.
Кроме очевидного преимущества в экономии дискового пространства, такой подход позволяет отправлять файлы, которые весят сотни мегабайт буквально за миллисекунды. Например, вам прислали в Telegram большой файл, пусть это будет целый фильм. Он вам понравился и вы решаете переслать это видео другому человеку.
На пересылку вы потратите секунды, при этом у вас не будет необходимости скачивать файл. По этому же принципу работает отправка файлов через их идентификаторы ID
.
Вот как забирать идентификаторы для разных типов контента:
- Аудио –
message.audio.file_id
- Документ –
message.document.file_id
- Видео –
message.video.file_id
И так далее. Единственное отличие будет у фотографий.