Решение ошибки "Bad Request: there is no document in the request" при отправке файла в Telegram API

При отправке документа через Telegram Bot API возникает следующая ситуация: код корректно работает на хостинге, но при запуске через OpenServer возвращается ошибка:

Array(
    [ok] => 
    [error_code] => 400
    [description] => Bad Request: there is no document in the request
)

Используется следующий PHP-код:

$FILE = $_SERVER['DOCUMENT_ROOT'].'/img.jpg';
$ch = curl_init();
curl_setopt_array($ch,array(
    CURLOPT_URL             =>'https://api.telegram.org/bot'.$TOKEN.'/sendDocument',
    CURLOPT_POST            => true,
    CURLOPT_RETURNTRANSFER  => true,
    CURLOPT_SSL_VERIFYHOST  => false,
    CURLOPT_SSL_VERIFYPEER  => false,
    CURLOPT_TIMEOUT         => 10,
    CURLOPT_POSTFIELDS      => json_encode(array(
        'chat_id' => $CHAT_ID,
        'document' => new \CURLFile($FILE)
    )),
));
echo curl_exec($ch);
curl_close($ch);

Причина ошибки

Проблема заключается в некорректной передаче данных в параметре CURLOPT_POSTFIELDS. При использовании json_encode() для массива, содержащего объект CURLFile, сериализация происходит неправильно, особенно в среде OpenServer.

Решение

Для корректной отправки файла через cURL необходимо передавать данные в формате массива без преобразования в JSON. Telegram API ожидает данные в формате multipart/form-data, который cURL формирует автоматически при передаче массива или строки с постфиксом @.

Замените строку с CURLOPT_POSTFIELDS на следующую:

CURLOPT_POSTFIELDS      => array(
    'chat_id' => $CHAT_ID,
    'document' => new \CURLFile($FILE)
),

Уберите вызов json_encode(). cURL самостоятельно установит правильный заголовок Content-Type: multipart/form-data и корректно обработает файл.

Исправленный код

$FILE = $_SERVER['DOCUMENT_ROOT'].'/img.jpg';
$ch = curl_init();
curl_setopt_array($ch,array(
    CURLOPT_URL             =>'https://api.telegram.org/bot'.$TOKEN.'/sendDocument',
    CURLOPT_POST            => true,
    CURLOPT_RETURNTRANSFER  => true,
    CURLOPT_SSL_VERIFYHOST  => false,
    CURLOPT_SSL_VERIFYPEER  => false,
    CURLOPT_TIMEOUT         => 10,
    CURLOPT_POSTFIELDS      => array(
        'chat_id' => $CHAT_ID,
        'document' => new \CURLFile($FILE)
    ),
));
echo curl_exec($ch);
curl_close($ch);

После этого изменения код будет стабильно работать как на хостинге, так и в локальном окружении OpenServer.