Передача файлов в Telegram-ботах с aiogram: полный обзор

Раздел: Сетевое программирование -> Боты и Telegram API

Отправка файлов через Telegram-бота на aiogram

Telegram-боты часто требуют отправки пользователям различных файлов: изображений, документов, аудио, видео. В aiogram (асинхронная библиотека для Python) это реализуется через методы класса Bot, такие как send_document, send_photo, send_video, send_audio и другие. Рассмотрим наиболее эффективный подход и альтернативные варианты, включая типичные проблемы.

Основное решение: отправка файла по file_id или URL

Самый быстрый способ – использовать уже загруженный на сервер Telegram file_id (строка) или внешний URL. Этот подход не требует повторной загрузки файла на сервер Telegram, если он уже известен.

from aiogram import Bot, Dispatcher, types
from aiogram.utils import executor

API_TOKEN = 'ВАШ_ТОКЕН'
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler(commands=['send_file'])
async def send_file_example(message: types.Message):
    # Отправка документа по file_id (получен ранее)
    file_id = 'BQACAgIAAxkBAA...'
    await bot.send_document(message.chat.id, file_id)
    
@dp.message_handler(commands=['send_photo'])
async def send_photo_example(message: types.Message):
    # Отправка фото по URL
    photo_url = 'https://example.com/image.jpg'
    await bot.send_photo(message.chat.id, photo_url)

if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)

Aiogram python file (отправка файлов через telegram-бота на aiogram в python)

Как отправить файл, который уже есть на сервере Telegram или по ссылке?

Возможные ошибки:

  • Неверный file_id – бот не может найти файл. Решение: убедиться, что file_id получен от того же бота и не устарел (file_id постоянны для одного бота).
  • Некорректный URL – сервер Telegram не может загрузить изображение. Решение: проверьте доступность URL и правильность MIME-типа.

Вариант 1: отправка локального файла (с компьютера)

Когда файл хранится на локальной файловой системе или генерируется на лету. Используется класс InputFile из aiogram.

from aiogram.types import InputFile

@dp.message_handler(commands=['local_doc'])
async def send_local_document(message: types.Message):
    doc = InputFile(path_or_bytesio='/home/user/my_document.pdf')
    await bot.send_document(message.chat.id, doc, caption='Локальный документ')

Как загрузить файл из папки на сервере бота?

Ошибка: файл не найден или нет прав. Решение: проверьте путь, права на чтение. Для Windows используйте двойные обратные слеши или raw-строки.

Вариант 2: отправка файла из памяти (BytesIO)

Если файл генерируется в оперативной памяти (например, результат работы библиотеки Pillow).

from io import BytesIO
from PIL import Image

@dp.message_handler(commands=['generate_image'])
async def send_generated_image(message: types.Message):
    img = Image.new('RGB', (100, 100), color='red')
    bio = BytesIO()
    img.save(bio, format='PNG')
    bio.seek(0)
    await bot.send_photo(message.chat.id, InputFile(bio, filename='red_square.png'))

Как отправить изображение, созданное в Python (например, график), не сохраняя на диск?

Некорректное имя файла без расширения – Telegram может не распознать тип. Решение: всегда передавайте filename с правильным расширением.

Вариант 3: отправка нескольких файлов одновременно

Используйте методы send_media_group для отправки группы медиафайлов (до 10).

from aiogram.types import MediaGroup, InputMediaPhoto, InputMediaDocument

@dp.message_handler(commands=['albums'])
async def send_album(message: types.Message):
    album = MediaGroup()
    album.attach(InputMediaPhoto(open('photo1.jpg', 'rb'), caption='Фото 1'))
    album.attach(InputMediaPhoto(open('photo2.jpg', 'rb')))
    album.attach(InputMediaDocument(open('doc.pdf', 'rb'), filename='doc.pdf'))
    await message.reply_media_group(media=album)
    # или await bot.send_media_group(message.chat.id, album)

Как отправить несколько фото и документов одним сообщением?

Превышение лимита (более 10) – Telegram не поддерживает. Решение: разбить на несколько групп. Для смешанных типов (фото+документ) группа будет отображаться некорректно? На самом деле разрешены только однотипные медиа в группе (все фото или все документы).

Вариант 4: отправка файла с клавиатурой или кнопками

Файл можно отправить вместе с inline-клавиатурой.

from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton

@dp.message_handler(commands['file_with_btn'])
async def send_file_with_keyboard(message: types.Message):
    keyboard = InlineKeyboardMarkup()
    keyboard.add(InlineKeyboardButton('Скачать', url='https://example.com'))
    await bot.send_document(message.chat.id, 'file_id_123', reply_markup=keyboard)

Как добавить кнопку под файлом?

Расширенные примеры и нестандартные сценарии

Пример 1: Отправка файла с переопределением имени и MIME-типа

Иногда нужно явно указать имя файла, которое увидит пользователь. Для этого используется InputFile с параметром filename. MIME-тип можно задать через headers, но обычно Telegram определяет его автоматически.

Пример
from aiogram.types import InputFile
import aiohttp

@dp.message_handler(commands=['rename_file'])
async def send_renamed_file(message: types.Message):
    # Скачиваем файл из интернета через aiohttp
    async with aiohttp.ClientSession() as session:
        async with session.get('https://example.com/files/data.csv') as resp:
            content = await resp.read()
    # Оборачиваем в BytesIO и задаём имя
    bio = BytesIO(content)
    input_file = InputFile(bio, filename='отчет_2025.csv')
    await bot.send_document(message.chat.id, input_file)
# Результат: пользователь увидит сообщение с файлом "отчет_2025.csv"

Пример 2: Отправка файла большого размера (до 50 МБ через бота)

Telegram ограничивает размер загружаемого файла через ботов до 50 МБ. Если файл больше, потребуется использовать серверный метод загрузки через sendDocument с разбивкой на части? На самом деле, aiogram поддерживает файлы до 50 МБ напрямую. Ошибки возникают, если файл превышает лимит.

Пример
@dp.message_handler(commands=['large_file'])
async def send_large_file(message: types.Message):
    try:
        # Допустим, файл размером 45 МБ
        with open('large_video.mp4', 'rb') as f:
            await bot.send_video(message.chat.id, InputFile(f))
    except Exception as e:
        await message.reply(f'Ошибка: {e}')
# Если файл превышает 50 МБ, будет ошибка: Request Entity Too Large. Решение – разделить файл на части или использовать Telegram API для прямой загрузки через сервер.

Пример 3: Отправка файла с кастомной подписью и parse_mode

Подпись (caption) поддерживает HTML и Markdown. Можно форматировать текст.

Пример
@dp.message_handler(commands=['caption_html'])
async def send_with_html_caption(message: types.Message):
    caption = 'Жирный текст\nКурсив\nСсылка'
    await bot.send_photo(message.chat.id, 'file_id_abc', caption=caption, parse_mode='HTML')
Пользователь увидит фото с форматированным текстом под ним.

Пример 4: Отправка файла с принудительной загрузкой (force document)

Если нужно отправить изображение как документ, а не как фото (чтобы не было превью в галерее), используйте send_document даже для изображений.

Пример
@dp.message_handler(commands=['force_doc'])
async def send_image_as_document(message: types.Message):
    # изображение отправится как файл .png
    await bot.send_document(message.chat.id, InputFile('image.png'))
    # Эквивалент без InputFile: await bot.send_document(message.chat.id, open('image.png', 'rb'))
В чате появится иконка документа, а не картинка.

Пример 5: Отправка файла с указанием thumb (миниатюры)

Для видео или документов можно задать миниатюру, которая будет отображаться в превью.

Пример
@dp.message_handler(commands=['with_thumb'])
async def send_video_with_thumb(message: types.Message):
    video_file = InputFile('video.mp4')
    thumb_file = InputFile('thumb.jpg')  # миниатюра PNG/JPG, не более 320x320
    await bot.send_video(message.chat.id, video_file, thumb=thumb_file)
Видео в сообщении будет иметь превью в виде вашей картинки.

Пример 6: Отправка файла из URL с асинхронной загрузкой

Рекомендуется не блокировать событийный цикл при загрузке по сети. Используйте aiohttp.

Пример
import aiohttp
from aiogram.types import InputFile
from io import BytesIO

@dp.message_handler(commands=['download_and_send'])
async def download_and_send(message: types.Message):
    url = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            data = await resp.read()
    bio = BytesIO(data)
    await bot.send_document(message.chat.id, InputFile(bio, filename='dummy.pdf'))
Бот скачает PDF и отправит его пользователю.

Пример 7: Использование file_id повторно для отправки

После того как файл загружен, Telegram возвращает file_id. Его можно сохранить в базе данных и использовать повторно без повторной загрузки.

Пример
@dp.message_handler(content_types=['document'])
async def get_file_id(message: types.Message):
    file_id = message.document.file_id
    # сохраняем file_id
    await message.reply(f'file_id сохранён: {file_id}')

@dp.message_handler(commands=['resend'])
async def resend_saved_file(message: types.Message):
    saved_file_id = 'полученный_ранее_file_id'
    await bot.send_document(message.chat.id, saved_file_id)
После повторного вызова команды /resend бот отправит тот же документ почти мгновенно.

Отправка файлов через Telegram-бота на aiogram в Python - comments

En
Aiogram python file (python)