Skip to content

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

И так далее. Единственное отличие будет у фотографий.

Contacts: teffal@mail.ru