Надсилання файлів — одна з базових операцій при інтеграції 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 повідомлень в секунду. Для складної інтеграції файлів розгляньте хостинг ботов з швидким накопичувачем і достатнім вихідним каналом.