Битрикс: два способа отправить файл

В битриксе с некоторых пор есть встроенный функционал для работы HTTP запросами. Т.е. не обязательно напрямую дёргать curl или привлекать какой-нибудь Guzzle. Плюс это или минус - оставлю решать каждому самостоятельно. Тут покажу два варианта, как можно отправить файл встроенным битриксовым методом. Это нужно, например, при интеграции с каким-то API. Примеров не нашлось ни в официальной документации, ни в полезном разжёвывании.

Вариант в теле запроса через send()

Тут надо обратить внимание на заголовок: тип "multipart/form-data"; наличие вложения в виде файла "Content-Disposition". Сам файл отправляем в теле запроса через вызов содержимого файла $file->getContents().

$result = [];
// Проверяем существование файла на сервере
$file = new \Bitrix\Main\IO\File(
    \Bitrix\Main\Application::getDocumentRoot() . '/upload/file.zip'
);
if ($file->isExists()) {
    $httpClient = new HttpClient(
        [
            'redirect'               => true, // true, если нужно выполнять редиректы
            'redirectMax'            => 3, // Максимальное количество редиректов
            'waitResponse'           => true, // true - ждать ответа, false - отключаться после запроса
            'socketTimeout'          => 30, // Таймаут соединения, сек
            'streamTimeout'          => 60, // Таймаут чтения ответа, сек, 0 - без таймаута
            'version'                => HttpClient::HTTP_1_1, // версия HTTP (HttpClient::HTTP_1_0 или HttpClient::HTTP_1_1)
            'proxyHost'              => '', // адрес
            'proxyPort'              => '', // порт
            'proxyUser'              => '', // имя
            'proxyPassword'          => '', // пароль
            'compress'               => false, // true - принимать gzip (Accept-Encoding: gzip)
            'charset'                => '', // Кодировка тела для POST и PUT
            'disableSslVerification' => true // true - отключить проверку ssl
        ]
    );

    // Добавляем заголовки запроса
    // Тут есть токен, который часто требуется в API:
    // где-то в коде надо получить токен, тут просто считаем, что токен есть
    $arHeader = [
        'Content-Type'        => 'multipart/form-data',
        'Authorization'       => 'Token ' . $obSomeClass->getToken(),
        'Content-Disposition' => 'attachment; filename=' . $file->getName()
    ];
    foreach ($arHeader as $name => $value) {
        $httpClient->setHeader($name, $value, true);
    }

    // Отправляем запрос
    $httpClient->query(
        'POST',
        'https://my-service.com/api/get-file/',
        $file->getContents()
    );
    if (200 === intval($httpClient->getStatus())) {
        $strResponse = $httpClient->getResult();
        if (!empty($strResponse)) {
            try {
                $arResponse = \Bitrix\Main\Web\Json::decode(
                    $strResponse
                );
            } catch (\Exception $exception) {
                echo 'Не удалось сформировать JSON: ' . $exception->getMessage();
            }
            if (!empty($arResponse)) {
                $result = $arResponse;
            }
        }
    }
}

print_r($result);
В программе Postman этот вид запроса настраивается так:

Вариант как одно из полей запроса методом post()

Тут заголовки остаются такие же, как и в предыдущем примере. А вот тело запроса формируется по-другому. В этом примере файл отправляется в одном из полей ("zip_archive"), сам файл считываем функцией fopen(). И метод битриксового API тут нужен именно post(), а не query(), как было в предыдущем примере.

$result = [];

// Проверяем существование файла на сервере
$filePath = \Bitrix\Main\Application::getDocumentRoot() . '/upload/file.zip';
$file = new \Bitrix\Main\IO\File($filePath);
if ($file->isExists()) {
    $httpClient = new HttpClient(
        [
            'redirect'               => true, // true, если нужно выполнять редиректы
            'redirectMax'            => 3, // Максимальное количество редиректов
            'waitResponse'           => true, // true - ждать ответа, false - отключаться после запроса
            'socketTimeout'          => 30, // Таймаут соединения, сек
            'streamTimeout'          => 60, // Таймаут чтения ответа, сек, 0 - без таймаута
            'version'                => HttpClient::HTTP_1_1, // версия HTTP (HttpClient::HTTP_1_0 или HttpClient::HTTP_1_1)
            'proxyHost'              => '', // адрес
            'proxyPort'              => '', // порт
            'proxyUser'              => '', // имя
            'proxyPassword'          => '', // пароль
            'compress'               => false, // true - принимать gzip (Accept-Encoding: gzip)
            'charset'                => '', // Кодировка тела для POST и PUT
            'disableSslVerification' => true // true - отключить проверку ssl
        ]
    );

    // Добавляем заголовки запроса
    // Тут есть токен, который часто требуется в API:
    // где-то в коде надо получить токен, тут просто считаем, что токен есть
    $arHeader = [
        'Content-Type'        => 'multipart/form-data',
        'Authorization'       => 'Token ' . $obSomeClass->getToken(),
        'Content-Disposition' => 'attachment; filename=' . $file->getName()
    ];
    foreach ($arHeader as $name => $value) {
        $httpClient->setHeader($name, $value, true);
    }

    // Отправляем запрос
    $httpClient->post(
        'POST',
        'https://my-service.com/api/get-file/',
        ['zip_archive' => fopen($filePath, 'rb')]
    );
    if (200 === intval($httpClient->getStatus())) {
        $strResponse = $httpClient->getResult();
        if (!empty($strResponse)) {
            try {
                $arResponse = \Bitrix\Main\Web\Json::decode(
                    $strResponse
                );
            } catch (\Exception $exception) {
                echo 'Не удалось сформировать JSON: ' . $exception->getMessage();
            }
            if (!empty($arResponse)) {
                $result = $arResponse;
            }
        }
    }
}

print_r($result);
В Postman это выглядит так:

Комментарии

Популярные сообщения из этого блога

Пропорциональное распределение суммы

Битрикс: своя геолокация