Скачать отчет по голосованию vote.AttachedVote.download

Если вы разрабатываете интеграции для Битрикс24 с помощью AI-инструментов (Codex, Claude Code, Cursor), подключите MCP-сервер, чтобы ассистент использовал официальную REST-документацию.

Scope: vote

Кто может выполнять метод: пользователь с правами чтения голосования

Метод vote.AttachedVote.download формирует и отдает для скачивания отчет по голосованию в указанном формате.

Особенности метода

Внимание! Этот метод является исключением из общего правила работы с REST API. В отличие от других методов, он возвращает не JSON-объект, а непосредственно содержимое файла с HTTP-заголовками, инициирующими скачивание в браузере.

Из-за этого стандартная функция BX24.callMethod() не может обработать ответ и вызовет ошибку. Для работы с этим методом необходимо выполнять прямой HTTP-запрос, как показано в примере кода на JS.

Параметры метода

Доступно три варианта вызова метода.

1. Через идентификатор прикрепленного опроса

Обязательные параметры отмечены *

Название
тип

Описание

attachId*
integer

Идентификатор прикрепленного голосования, получить можно методами vote.AttachedVote.get или vote.AttachedVote.getMany

2. Через элемент с опросом

Обязательные параметры отмечены *

Название
тип

Описание

moduleId*
string

Идентификатор модуля, возможные значения:

  • Im для опроса в чате,
  • blog для опроса в ленте

entityType*
string

Тип объекта, возможные значения:

  • Bitrix\\Vote\\Attachment\\ImMessageConnector для опроса в чате,
  • Bitrix\\Vote\\Attachment\\BlogPostConnector для опроса в ленте

entityId*
integer

Идентификатор элемента, возможные значения:

  • id сообщения чата с опросом, получить можно методом vote.Integration.Im.send,
  • id поста с опросом в ленте, получить можно методом log.blogpost.get

3. Через подписанный идентификатор

Обязательные параметры отмечены *

Название
тип

Описание

signedAttachId*
string

Подписанный идентификатор прикрепления, получить можно методом vote.AttachedVote.get, параметр ответа signedAttachId

Примеры кода

Как использовать примеры в документации

curl -X POST \
        -L \
        -o **put_file_name**.xls \
        -H "Content-Type: application/json" \
        -d '{"attachId":**put_attach_id**}' \
        "https://**put_your_bitrix24_address**/rest/**put_your_user_id_here**/**put_your_webhook_here**/vote.AttachedVote.download"
        
        
        
curl -X POST \
        -L \
        -o **put_file_name**.xls \
        -H "Content-Type: application/json" \
        -d '{"attachId":**put_attach_id**, "auth": "**put_access_token_here**"}' \
        "https://**put_your_bitrix24_address**/rest/vote.AttachedVote.download"
        
function downloadVoteReportById(attachId)
        {
            // 1. Получаем данные для авторизации из библиотеки BX24
            const auth = BX24.getAuth();
            if (!auth)
            {
                return;
            }
        
            // 2. Формируем URL для прямого запроса к REST API
            const restUrl = new URL(`https://${auth.domain}/rest/vote.AttachedVote.download`);
            restUrl.searchParams.append('auth', auth.access_token);
            restUrl.searchParams.append('attachId', attachId);
        
            console.log(`Запрос на скачивание: ${restUrl}`);
        
            // 3. Выполняем запрос и обрабатываем ответ как бинарный файл (blob)
            fetch(restUrl)
                .then(response => {
                    if (!response.ok)
                    {
                        // Если запрос не прошел, пытаемся обработать стандартную JSON-ошибку Bitrix24
                        return response.json().catch(() => {
                            // Если тело ответа - не JSON, выбрасываем общую сетевую ошибку
                            throw new Error(`Сетевая ошибка: ${response.status} ${response.statusText}`);
                        }).then(errorData => {
                            // Если удалось распарсить JSON-ошибку
                            throw new Error(`Ошибка API: ${errorData.error_description || 'Неизвестная ошибка'}`);
                        });
                    }
                    // В случае успеха получаем данные как бинарный объект
                    return response.blob();
                })
                .then(blob => {
                    // 4. Создаем "невидимую" ссылку и инициируем скачивание в браузере
                    const url = window.URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.style.display = 'none';
                    a.href = url;
                    
                    // Задаем имя файла, которое увидит пользователь
                    a.download = `vote_report_${attachId}.${fileType}`;
                    
                    document.body.appendChild(a);
                    a.click();
                    
                    // Очищаем временные данные
                    window.URL.revokeObjectURL(url);
                    document.body.removeChild(a);
                })
                .catch(error => {
                    console.error('Ошибка при скачивании отчета:', error);
                    alert(`Не удалось скачать отчет: ${error.message}`);
                });
        }
        
<?php
        // Этот файл обычно содержит константы для подключения или настройки автозагрузчика
        require_once('src/crest.php');
        
        /**
        * Функция для скачивания отчета с помощью прямого HTTP-запроса,
        * так как метод vote.AttachedVote.download возвращает не JSON, а содержимое файла.
        *
        * @param array $params - Параметры REST-метода (например, ['attachId' => 1])
        */
        function downloadVoteReport(array $params, string $saveToFile): bool
        {
            // 1. Получаем настройки авторизации. 
            // CRest::getAppSettings() вернет либо данные для OAuth, либо для вебхука.
            // В самом crest.php меняем модификатор доступа на public для этого метода
            $authData = CRest::getAppSettings();
        
            if (empty($authData)) {
                echo "Ошибка: не удалось получить настройки авторизации. Проверьте crest.php/settings.php.\n";
                return false;
            }
        
            // 2. Определяем URL для запроса
            if (!empty($authData['is_web_hook']) && $authData['is_web_hook'] === 'Y') {
                // Случай с вебхуком
                $url = $authData['client_endpoint'] . 'vote.AttachedVote.download';
                $queryParams = $params;
            } else {
                // Случай с OAuth-приложением
                $url = $authData['client_endpoint'] . 'vote.AttachedVote.download';
                $params['auth'] = $authData['access_token'];
                $queryParams = $params;
            }
        
            $url .= '?' . http_build_query($queryParams);
            echo "URL запроса: " . $url . "\n";
        
            // 3. Выполняем запрос с помощью cURL
            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => $url,
                CURLOPT_HEADER => false,        // Не включать заголовки в ответ
                CURLOPT_RETURNTRANSFER => true, // Вернуть ответ в виде строки, а не выводить в браузер
                CURLOPT_USERAGENT => 'CRest based downloader',
                CURLOPT_FOLLOWLOCATION => true, // Следовать за редиректами
            ]);
        
            $response = curl_exec($curl);
            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            $error = curl_error($curl);
            curl_close($curl);
        
            // 4. Проверяем результат и сохраняем файл
            if ($error) {
                echo "Ошибка cURL: " . $error . "\n";
                return false;
            }
        
            if ($httpCode >= 400) {
                echo "Сервер вернул ошибку HTTP " . $httpCode . ".\n";
                // Попытка декодировать ошибку, если она в формате JSON
                $errorData = json_decode($response, true);
                if ($errorData && isset($errorData['error_description'])) {
                    echo "Описание ошибки: " . $errorData['error_description'] . "\n";
                } else {
                    echo "Тело ответа: " . $response . "\n";
                }
                return false;
            }
            
            // Если все хорошо, сохраняем ответ в файл
            if (file_put_contents($saveToFile, $response)) {
                echo "Файл успешно сохранен в: " . $saveToFile . "\n";
                return true;
            } else {
                echo "Не удалось сохранить файл в: " . $saveToFile . "\n";
                return false;
            }
        }
        
        
        // --- Пример использования ---
        
        $attachId = 1;
        $fileType = 'xls';
        $fileName = "vote_report_{$attachId}.{$fileType}";
        
        $result = downloadVoteReport(
            [
                'attachId' => $attachId,
            ],
            $fileName
        );
        
        if ($result) {
            echo "Задание выполнено.\n";
        } else {
            echo "Во время выполнения произошли ошибки.\n";
        }
        

Обработка ответа

HTTP-статус: 200 OK

В случае успешного выполнения, сервер возвращает не JSON-объект, а непосредственно содержимое файла с HTTP-заголовками, инициирующими скачивание в браузере Content-Disposition: attachment.

Обработка ошибок

HTTP-статус: 4xx

{
            "error": "ATTACH_NOT_FOUND",
            "error_description": "Attach not found"
        }
        

Название
тип

Описание

error
string

Строковый код ошибки. Может состоять из цифр, латинских букв и знака подчеркивания

error_description
error_description

Текстовое описание ошибки. Описание не предназначено для показа конечному пользователю в необработанном виде

Возможные коды ошибок

Код

Описание

ATTACH_NOT_FOUND

Голосование не найдено

ATTACH_READ_ACCESS_DENIED

Нет прав для участия в голосовании

Статусы и коды системных ошибок

HTTP-статус: 20x, 40x, 50x

Описанные ниже ошибки могут возникнуть при вызове любого метода

Статус

Код
Текст ошибки

Описание

500

INTERNAL_SERVER_ERROR
Internal server error

Возникла внутренняя ошибка сервера, обратитесь к администратору сервера или в техническую поддержку Битрикс24

500

ERROR_UNEXPECTED_ANSWER
Server returned an unexpected response

Возникла внутренняя ошибка сервера, обратитесь к администратору сервера или в техническую поддержку Битрикс24

503

QUERY_LIMIT_EXCEEDED
Too many requests

Превышен лимит на интенсивность запросов

405

ERROR_BATCH_METHOD_NOT_ALLOWED
Method is not allowed for batch usage

Текущий метод не разрешен для вызова с помощью batch

400

ERROR_BATCH_LENGTH_EXCEEDED
Max batch length exceeded

Превышена максимальная длина параметров, переданных в метод batch

401

NO_AUTH_FOUND
Wrong authorization data

Неверный access-токен или код вебхука

400

INVALID_REQUEST
Https required

Для вызовов методов требуется использовать протокол HTTPS

503

OVERLOAD_LIMIT
REST API is blocked due to overload

REST API заблокирован из-за перегрузки. Это ручная индивидуальная блокировка, для снятия необходимо обращаться в техническую поддержку Битрикс24

403

ACCESS_DENIED
REST API is available only on commercial plans

REST API доступен только на коммерческих планах

403

INVALID_CREDENTIALS
Invalid request credentials

У пользователя, с чьим access-токеном или вебхуком был вызван метод, не хватает прав

404

ERROR_MANIFEST_IS_NOT_AVAILABLE
Manifest is not available

Манифест недоступен

403

insufficient_scope
The request requires higher privileges than provided by the webhook token

Запрос требует более высоких привилегий, чем предоставляет токен вебхука

401

expired_token
The access token provided has expired

Предоставленный access-токен доступа истек

403

user_access_error
The user does not have access to the application

Пользователь не имеет доступа к приложению. Это означает, что приложение установлено, но администратор портала разрешил доступ к этому приложению только конкретным пользователям

500

PORTAL_DELETED
Portal was deleted

Публичная часть сайта закрыта. Чтобы открыть публичную часть сайта на коробочной установке отключите опцию «Временное закрытие публичной части сайта». Путь к настройке: Рабочий стол > Настройки > Настройки продукта > Настройки модулей > Главный модуль > Временное закрытие публичной части сайта

Продолжите изучение