Надсилання фотографій і документів в Telegram через PHP: ліміти multipart, file_id і Bot API

Надсилання файлів — одна з базових операцій при інтеграції Telegram-бот з компанією: чеки, каталоги, ціни, фото товарів. Здавалося б, Bot API охоплює все двома методами — sendPhoto і sendDocument. Але є нюанси: cURL не надсилає файли, як звичайний масив Post, file_id може бути використаний повторно, а розмір файлів є більш обмежувальним, ніж здається. Давайте розберемо його по порядку.

Чому не file_get_contents для API

У навчальних прикладах прийнято надсилати дані через file_get_contents з потоком http. Це працює для простих запитів, але не для файлів. Telegram приймає фотографії та документи лише через multipart/form-data — формат, в якому кожен параметр (включаючи файл) кодується як окрема частина тіла запиту з заголовками Зміст-диспозиція.

Стандартна бібліотека cURL в PHP робить це нативно: вам просто потрібно вказати CURLOPT_POST, передайте текстові поля через CURLOPT_POSTFIELDS як масив, а файл як ключ з префіксом @ (або об 'єкт CURLFile pHP 5.5+).

sendPhoto: надсилання локального файлу

Мінімальний робочий приклад надсилання фотографії, яка вже є на серверному диску:

Зверніть увагу: CURLFile приймає тип MIME та початкове ім 'я файлу. Telegram визначить сам формат, але вказівка image/jpeg від кулі image. png прискорює перевірку.

sendDocument: відправити PDF, XLSX, ZIP

Принцип той самий, але з двома відмінностями: ліміт більший (до 50 МБ проти 10 МБ на фото) і може передаватися caption — текст до 1024 символів. Для цін, рахунків-фактур та контрактів це стандартний сценарій:

file_id: повторне використання замість повторного завантаження

Коли ви відправляєте файл вперше, Telegram повертає об 'єкт Photo від кулі Document з полем File ID. Цей ідентифікатор є рядковим значенням форми AgACAgIAAxkBAAIBZ2...Може використовуватися в наступних запитах без повторного завантаження файлу:

Це критично для каталогів: завантажте зображення товару один раз при створенні картки, збережіть File ID до бази даних, і коли ви надсилаєте його клієнту, ви просто передаєте ідентифікатор. Збережіть як трафік, так і час виклику API.

Важливо: File ID пов 'язаний з ботом. Ідентифікатор, отриманий в одному боті, не може бути використаний в іншому. Термін служби File ID не задокументовано, але на практиці залишаються робочі місяці.

Обмеження розміру: 10 МБ для фотографій, 50 МБ для документів

Telegram встановлює такі обмеження:

  • sendPhoto — локальний файл до 10 МБ, за URL-адресою до 10 МБ;
  • sendDocument — локальний файл до 50 МБ, за URL до 50 МБ (для деяких типів файлів може бути менше);
  • фотографія автоматично стискається до 1280× 1280 пікселів, якщо вона перевищує.

На практиці перевірте розмір розмір файлу перед надсиланням. Якщо файл більший за ліміт, надішліть його як архів або стисліть.

Коли передавати URL-адресу замість завантаження

О sendPhoto і sendDocument існує альтернативний спосіб: параметр Photo від кулі document приймає пряме посилання на файл в Інтернеті. У цьому випадку Telegram завантажує сам контент — ваш сервер не витрачає трафік на завантаження та відправку.

Використовуйте URL-адресу, коли:

  • файл вже знаходиться в CDN, S3 або загальнодоступному сховищі.
  • ви не хочете завантажувати один і той самий файл знову щоразу, коли завантажуєте його.
  • ваш сервер обмежений у вихідному трафіку або виконанні.

Використовуйте багатокомпонентне завантаження, коли:

  • файл генерується динамічно (рахунок-фактура у форматі PDF, звіт) і не зберігається публічно;
  • вам потрібно гарантувати доступність файлу (URL-адреса може «померти»);
  • Вимагати caption з розміткою (емодзі, форматування) — працює як з URL-адресами, так і з file_id.

Типові пастки

Помилка: "Помилковий запит: неправильний хост URL-адреси". Telegram не приймає посилання для авторизації. (https://user:pass@example.com/file.jpg) та місцеві адреси (вул.http://localhost/...) Сервер бота повинен мати доступ до URL-адреси.

Помилка: порожній файл CURLFile або файл не знайдено. Перевіряйте. file_exists() перед відправкою. Якщо файл генерується в пам 'яті (наприклад, через imagejpeg()), запишіть у тимчасовий файл за допомогою tempnam() або використовуйте потік php://memory з обгорткою CURLFile.

Помилка: "Файл завеликий". Перевіряйте. розмір файлу та ліміти методу. Якщо ви надсилаєте File ID, обмеження не застосовуються — повторне надсилання одного й того ж файлу необмежене.

Підсумок: коли підхід

Для каталогів і статичних носіїв — завантажено один раз, збережено File ID до бази даних, надіслати за ідентифікатором. Для динамічних документів (рахунків-фактур, договорів) — генерувати, надсилати через CURLFile. Для контенту з CDN — передаємо URL, зберігаємо ресурси сервера.

Правильна робота з файлами в Telegram-боті скорочує час відгуку, економить трафік і зменшує навантаження на Bot API в межах 20–60 повідомлень в секунду. Для складної інтеграції файлів розгляньте хостинг ботов з швидким накопичувачем і достатнім вихідним каналом.

Нові статті — у Telegram

Розбираємо, що автоматизувати в бізнесі та як це працює на практиці. Без спаму.