При создании интеграций с Telegram на PHP часто возникает необходимость отправки медиафайлов и документов. В то время как отправка простых текстовых сообщений не вызывает сложностей, передача файлов требует понимания того, как Telegram Bot API работает с бинарными данными, кэшированием файлов и ограничениями по размеру.
В этом руководстве показано, как загружать локальные файлы в Telegram с помощью CURLFile (который отправляет запрос multipart/form-data ), как извлекать и повторно использовать полученный file_id для экономии трафика, а также когда следует использовать публичные URL вместо прямой загрузки. Мы не претендуем на создание полноценной системы управления медиафайлами; это чистая, готовая к продакшену реализация механики передачи файлов в Telegram.
Загрузка локального файла через multipart/form-data
Чтобы отправить локальный файл с вашего сервера в Telegram, необходимо использовать запрос POST с типом контента multipart/form-data . В PHP это достигается путем передачи ассоциативного массива в CURLOPT_POSTFIELDS , содержащего объект CURLFile .
Вот готовый, надежный скрипт для загрузки локального PDF-документа с помощью sendDocument :
<?php
$token = getenv('TELEGRAM_BOT_TOKEN');
$chatId = getenv('TELEGRAM_CHAT_ID');
$filePath = __DIR__ . '/receipt.pdf';
if (!$token || !$chatId) {
throw new Exception('Missing environment configuration.');
}
if (!file_exists($filePath)) {
throw new Exception('Target file does not exist: ' . $filePath);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.telegram.org/bot{$token}/sendDocument");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// CURLFile automatically sets the content-type to multipart/form-data
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'chat_id' => $chatId,
'document' => new CURLFile($filePath, 'application/pdf', 'receipt.pdf'),
'caption' => 'Your requested receipt'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
$errorMsg = curl_error($ch);
curl_close($ch);
throw new Exception('cURL Error: ' . $errorMsg);
}
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('Telegram API returned non-200 status: ' . $httpCode . ' Response: ' . $response);
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Failed to parse Telegram JSON response.');
}
if (!isset($data['ok']) || !$data['ok']) {
throw new Exception('Telegram API Error: ' . ($data['description'] ?? 'Unknown error'));
}
// Extract the file_id for future reuse
$fileId = $data['result']['document']['file_id'];
echo "File uploaded successfully. File ID: " . $fileId . "\n";
Повторное использование file_id
После загрузки файла Telegram сохраняет его на своих серверах и присваивает ему уникальный file_id . Если вам нужно отправить точно такой же файл другому пользователю или тому же пользователю еще раз, не загружайте файл повторно.
Повторная загрузка тратит ресурсы процессора сервера, память и пропускную способность сети. Вместо этого передайте file_id в качестве простого строкового параметра. Telegram мгновенно найдет файл на своей стороне.
<?php
$anotherChatId = getenv('TELEGRAM_ANOTHER_CHAT_ID');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.telegram.org/bot{$token}/sendDocument");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Pass the file_id string directly instead of a CURLFile object
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'chat_id' => $anotherChatId,
'document' => $fileId,
'caption' => 'Shared copy of the receipt'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
$errorMsg = curl_error($ch);
curl_close($ch);
throw new Exception('cURL Error: ' . $errorMsg);
}
curl_close($ch);
$data = json_decode($response, true);
if (isset($data['ok']) && $data['ok']) {
echo "File sent successfully using cached file_id.\n";
}
Когда использовать публичный URL
Вместо загрузки файла с локального диска вы можете передать Telegram публичный HTTP-URL этого файла.
- Плюсы: Вашему PHP-серверу не нужно предварительно скачивать файл на локальный диск, что экономит дисковое пространство и локальный ввод-вывод.
- Минусы: Telegram должен сам скачать файл с вашего сервера. Если ваш сервер работает медленно или имеет строгие правила брандмауэра, время ожидания запроса может истечь. Кроме того, Telegram кэширует файлы, отправленные по URL. Если содержимое файла на вашем сервере изменится, но URL останется прежним, Telegram может продолжить отправку старой, кэшированной версии.
Чтобы отправить файл по URL, просто передайте строку URL в параметрах запроса:
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'chat_id' => $chatId,
'document' => 'https://yourdomain.com/static/terms.pdf',
'caption' => 'Terms of Service'
]);
Ограничения и нюансы для продакшена
-
Ограничения по размеру:
- Для обычных ботов, использующих стандартные облачные серверы Telegram Bot API, максимальный размер загружаемого файла составляет 50 МБ.
- При отправке файлов через публичный URL лимит составляет 20 МБ.
- Если вашему приложению требуется обработка файлов размером до 2000 МБ, вам необходимо развернуть и запустить собственный локальный сервер Telegram Bot API.
Настройка таймаута:
Загрузка больших файлов (близких к 50 МБ) при медленном соединении может превысить стандартные таймауты выполнения PHP и cURL. Всегда устанавливайте явные таймауты для вашего дескриптора cURL при загрузке файлов:
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // Allow up to 60 seconds for the upload
-
MIME-типы:
При использовании
CURLFileвсегда указывайте правильный MIME-тип (второй параметр) и имя файла (третий параметр). Если оставить их пустыми, Telegram может отклонить файл или отобразить его конечному пользователю с общим, нечитаемым расширением.
Если вам нужна профессиональная помощь в проектировании, масштабировании или развертывании высокопроизводительных интеграций с Telegram, свяжитесь с BotCreator — студией, которая создает Telegram-ботов и Mini Apps.
Комментарии (0)
Пока нет комментариев — будьте первым.