Как отправить XML-файл из 1С 7.7 на сервер и исправить ошибку 406 Not Acceptable?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При интеграции 1С 7.7 с внешними системами часто возникает задача отправки данных, например, в формате XML, на удаленный сервер. В процессе можно столкнуться с различными HTTP-ошибками, одна из которых — 406 Not Acceptable. Давайте разберемся, почему она возникает и какие существуют надежные способы для отправки файлов из старой доброй "семерки".

Проанализируем ситуацию: при попытке отправить XML-файл с помощью POST-запроса сервер возвращает ошибку 406 Not Acceptable. Это означает, что сервер не может предоставить ответ в формате, который запрашивает клиент. Часто разработчики концентрируются на заголовке Content-Type, который описывает отправляемые данные, но корень проблемы может быть в другом.

Основная причина ошибки 406 — несоответствие заголовка Accept в запросе клиента и форматов, которые может отдать сервер. Клиент должен явно указать, какой тип контента он готов принять в ответе. Если этот заголовок не указан или его значение не устраивает сервер, возникает данная ошибка.

Хотя в обсуждаемой проблеме использовалась сторонняя компонента HTTPS77.dll, для которой не нашлось готового примера, существуют другие внешние компоненты для работы по HTTP(S) и более надежные стандартные инструменты, которые прекрасно справляются с этой задачей. Рассмотрим их подробно.

Решение 1: Использование стандартных COM-объектов Windows

Самый надежный и не требующий установки внешних компонент способ (наряду с использованием библиотек готовых функций для 1С 7.7) — это использование встроенных в Windows COM-объектов. Для работы с HTTP-запросами в 1С 7.7 (например, для загрузки курсов валют) идеально подходят MSXML2.ServerXMLHTTP и WinHTTP.WinHTTPRequest.

Использование MSXML2.ServerXMLHTTP

Этот объект является частью библиотеки Microsoft XML Core Services и отлично подходит для работы с XML. Он корректно обрабатывает кодировки и позволяет работать с XML-документами напрямую. Важно использовать последнюю доступную версию объекта, например, MSXML2.ServerXMLHTTP.6.0, так как она поддерживает современные протоколы шифрования (TLS 1.2), без которых подключиться к большинству современных серверов не получится.

Посмотрим на пример кода для отправки XML-файла:


// Функция для отправки XML-файла на сервер
// Возвращает текст ответа сервера или описание ошибки
Функция ОтправитьXMLНаСервер(ПутьКФайлу, URL)

    // 1. Создаем объект для HTTP-запросов
    Попытка
        HTTPЗапрос = СоздатьОбъект("MSXML2.ServerXMLHTTP.6.0");
    Исключение
        Возврат "Не удалось создать объект MSXML2.ServerXMLHTTP.6.0. Проверьте, установлены ли Microsoft Core XML Services 6.0.";
    КонецПопытки;

    // 2. Создаем и загружаем XML-документ из файла
    // Этот шаг необязателен, можно прочитать файл в текстовую переменную
    // Но работа через DOM-объект более структурирована
    Попытка
        XMLДокумент = СоздатьОбъект("MSXML2.DOMDocument.6.0");
        XMLДокумент.async = 0; // Устанавливаем синхронный режим загрузки
        Если XMLДокумент.load(ПутьКФайлу) = 0 Тогда
            Возврат "Ошибка загрузки XML-файла: " + XMLДокумент.parseError.reason;
        КонецЕсли;
    Исключение
        Возврат "Не удалось создать объект MSXML2.DOMDocument.6.0.";
    КонецПопытки;

    // 3. Открываем соединение методом POST
    // Третий параметр (0 или False) означает синхронный режим выполнения
    HTTPЗапрос.open("POST", URL, 0);

    // 4. Устанавливаем ключевые заголовки запроса
    // Сообщаем серверу, что мы отправляем XML в кодировке UTF-8
    HTTPЗапрос.setRequestHeader("Content-Type", "application/xml; charset=utf-8");
    
    // Сообщаем серверу, что мы готовы принять ответ в формате XML
    // Это ключевой момент для предотвращения ошибки 406 Not Acceptable
    HTTPЗапрос.setRequestHeader("Accept", "application/xml");

    // 5. Отправляем тело запроса (содержимое XML)
    // Метод send может принимать как строку, так и DOM-объект
    HTTPЗапрос.send(XMLДокумент);

    // 6. Анализируем ответ сервера
    Если HTTPЗапрос.status = 200 Тогда // 200 OK - успешное выполнение
        Возврат HTTPЗапрос.responseText;
    Иначе
        Возврат "Ошибка: " + HTTPЗапрос.status + " " + HTTPЗапрос.statusText;
    КонецЕсли;

КонецФункции

// Пример вызова функции
Процедура ВыполнитьОтправку()
    ПутьКФайлу = "C:\temp\data.xml";
    URL = "https://адрес.сервера/api/upload";
    
    Ответ = ОтправитьXMLНаСервер(ПутьКФайлу, URL);
    Сообщить(Ответ);
КонецПроцедуры

В этом примере мы по шагам разобрали весь процесс: создали объекты, установили правильные заголовки, отправили данные и обработали результат. Главное внимание здесь стоит уделить строке HTTPЗапрос.setRequestHeader("Accept", "application/xml");, которая и решает проблему с ошибкой 406.

Альтернатива: WinHTTP.WinHTTPRequest.5.1

Это еще один мощный COM-объект для работы с HTTP. Он считается более современным и универсальным, чем ServerXMLHTTP, и также отлично поддерживает современные протоколы безопасности. Синтаксис работы с ним очень похож.

Решение 2: Использование внешней утилиты cURL

cURL — это мощнейшая утилита командной строки для передачи данных по различным протоколам, включая HTTP/HTTPS. Её использование из 1С 7.7 — это отличный способ обойти ограничения старой платформы и COM-объектов, особенно в части поддержки новейших стандартов шифрования.

Преимущества cURL:

  1. Поддержка современных протоколов. Всегда свежая версия cURL будет поддерживать TLS 1.2, 1.3 и другие актуальные стандарты безопасности.
  2. Гибкость. Огромное количество параметров командной строки позволяет настроить любой, даже самый сложный запрос.
  3. Надежность. cURL — это зрелый и проверенный временем инструмент, который стабильно работает с большими объемами данных.

Для вызова утилиты из 1С 7.7 можно использовать функцию ЗапуститьПриложение() или КомандаСистемы(). Результат работы можно перенаправить в текстовый файл и затем прочитать его средствами 1С.

Рассмотрим пример команды для отправки нашего XML-файла:

curl -X POST -H "Content-Type: application/xml" -H "Accept: application/xml" --data-binary "@C:\temp\data.xml" https://адрес.сервера/api/upload -o C:\temp\response.txt -w "%{http_code}" -s

Разберем эту команду по частям:

Чтобы выполнить это из 1С, можно написать следующий код:


Процедура ОтправитьФайлЧерезCurl()
    ПутьКФайлу = "C:\temp\data.xml";
    ПутьКОтвету = "C:\temp\response.txt";
    ПутьКФайлуКода = "C:\temp\http_code.txt";
    URL = "https://адрес.сервера/api/upload";

    // Формируем команду для выполнения
    Команда = "curl -X POST -H ""Content-Type: application/xml"" " +
            "-H ""Accept: application/xml"" " +
            "--data-binary ""@" + ПутьКФайлу + """ " +
            URL + " " +
            "-o " + ПутьКОтвету + " " +
            "-w ""%{http_code}"" -s > " + ПутьКФайлуКода;

    // Запускаем команду и ждем ее завершения
    ЗапуститьПриложение(Команда, "", 1);

    // Читаем код ответа
    Текст = СоздатьОбъект("Текст");
    Текст.Открыть(ПутьКФайлуКода);
    КодОтвета = Число(Текст.ПолучитьСтроку(1));
    Текст.Закрыть();

    Если КодОтвета = 200 Тогда
        // Читаем тело ответа, если нужно
        Текст.Открыть(ПутьКОтвету);
        ТелоОтвета = "";
        Для i = 1 По Текст.КоличествоСтрок() Цикл
            ТелоОтвета = ТелоОтвета + Текст.ПолучитьСтроку(i);
        КонецЦикла;
        Текст.Закрыть();
        Сообщить("Успешно! Ответ сервера: " + ТелоОтвета);
    Иначе
        Сообщить("Ошибка! HTTP-код: " + КодОтвета);
    КонецЕсли;
КонецПроцедуры

Также стоит упомянуть, что для более тесной интеграции cURL и 1С 7.7 существуют готовые внешние компоненты (например, curl1c.dll), которые оборачивают функциональность утилиты в удобные методы 1С, избавляя от необходимости работать с командной строкой и файлами.

Выводы

Итак, чтобы успешно отправить XML-файл из 1С 7.7 и избежать ошибки 406 Not Acceptable, необходимо:

  1. Использовать надежные инструменты. Вместо редких или устаревших компонент лучше выбрать стандартные COM-объекты (MSXML2.ServerXMLHTTP.6.0) или мощную внешнюю утилиту (cURL).
  2. Правильно устанавливать заголовки. Помимо заголовка Content-Type, описывающего тело вашего запроса, не забывайте указывать заголовок Accept, чтобы сообщить серверу, какой формат ответа вы ожидаете (например, application/xml).
  3. Учитывать требования к безопасности. Убедитесь, что ваш инструмент поддерживает современные протоколы шифрования TLS 1.2+, иначе соединение с сервером может быть не установлено.

Выбор между COM-объектом и cURL зависит от задачи. Для простых запросов внутри защищенной сети достаточно COM. Для сложных интеграций с современными веб-сервисами, требующими гибкой настройки и поддержки последних стандартов безопасности, cURL будет более предпочтительным вариантом.

← На главную