Как скачать файл по протоколу HTTPS в 1С 7.7: обходим ограничения компоненты v7plus

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

При интеграции устаревших конфигураций 1С:Предприятие 7.7 с современными веб-сервисами разработчики неизбежно сталкиваются с проблемой перехода сайтов на защищенный протокол HTTPS. Традиционная компонента v7plus.dll (а именно объект Addin.V7HttpReader) была спроектирована в эпоху доминирования протокола HTTP и физически не умеет выполнять SSL-рукопожатие и работать с современными протоколами шифрования TLS 1.2 и TLS 1.3. При попытке вызвать метод ПолучитьКакФайл для адреса, начинающегося с "https://", система выдает критическую ошибку: "Компонента V7Plus : Попытка использования недопустимого протокола обмена".

В этой статье мы подробно разберем, почему стандартные средства терпят неудачу, проанализируем причины ошибок при попытках использовать системные COM-объекты и рассмотрим четыре надежных альтернативных способа скачивания файлов по протоколу HTTPS в среде 1С 7.7.

Почему стандартный WinHttp обрезает бинарные файлы до 1 Кб?

Попытки разработчиков обойти ограничения v7plus.dll с помощью системного объекта WinHttp.WinHttpRequest.5.1 часто приводят к другой проблеме: скачиваемый файл (например, архив .7z или картинка) сохраняется на диск поврежденным или обрезанным до размера около 1 Килобайта. Выясним причину этого поведения.

В типичном коде для чтения ответа часто используется свойство ResponseText, а полученная строка записывается на диск через стандартный объект 1С Текст:


Ответ = WinHttp.ResponseText;
Файл = СоздатьОбъект("Текст");
Файл.ДобавитьСтроку(Ответ);
Файл.Записать(ПутьКФайлу);

Такой подход принципиально неверен для бинарных данных по двум причинам:

  1. Проблема нулевого байта (Null-terminated string): Строковые переменные во внутреннем движке 1С 7.7 представляют собой классические строки C++, где признаком окончания строки является символ с нулевым кодом (0x00). Любой бинарный файл (архив, изображение, PDF) содержит множество нулевых байтов. Как только 1С встречает первый такой байт в потоке ResponseText, она считает, что строка закончилась, и обрезает запись. Именно поэтому файл на диске оказывается размером всего в несколько сотен байт.
  2. Проблема кодировок: Свойство ResponseText пытается интерпретировать бинарный поток как текст в определенной кодировке (обычно UTF-8 или Windows-1251), что необратимо искажает двоичные данные.

Для работы с бинарными данными необходимо использовать свойство ResponseBody (которое возвращает массив байтов SafeArray) и объект ADODB.Stream. Однако напрямую передать SafeArray в метод Stream.Write() из 1С 7.7 невозможно из-за ограничений OLE-контейнера платформы, который выдает ошибку совместимости типов. Ниже мы рассмотрим, как решить эту проблему изящным способом.

Решение №1. Использование WinHttp совместно с MSScriptControl (без повреждения файлов)

Чтобы обойти ограничение платформы 1С 7.7 на передачу бинарных массивов SafeArray, мы можем задействовать стандартный системный компонент MSScriptControl.ScriptControl. С его помощью мы выполним запись бинарного ответа в поток средствами движка VBScript, который отлично справляется с приведением типов COM-объектов.

Рассмотрим по шагам готовый код функции для скачивания файлов:


Процедура СкачатьФайлHTTPS(АдресРесурса, ПутьСохранения)
    Попытка
        // Создаем объект HTTP-запроса
        WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
        
        // Открываем синхронное соединение (третий параметр - 0)
        WinHttp.Open("GET", АдресРесурса, 0); 
        
        // Отправляем запрос на сервер
        WinHttp.Send();
        
        // Проверяем статус ответа (200 - OK)
        Если WinHttp.Status = 200 Тогда
            // Создаем ADO-поток для работы с бинарными данными
            Stream = СоздатьОбъект("ADODB.Stream");
            Stream.Type = 1; // 1 = adTypeBinary (работаем с двоичными данными)
            Stream.Mode = 3; // 3 = adModeReadWrite (разрешаем чтение и запись)
            Stream.Open();
            
            // Используем скрипт-контроль для обхода ограничений 1С на тип SafeArray
            Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
            Скрипт.Language = "VBScript";
            
            // Передаем наши OLE-объекты внутрь контекста скрипта
            Скрипт.AddObject("Stream", Stream);
            Скрипт.AddObject("WinHttp", WinHttp);
            
            // Записываем бинарное тело ответа напрямую в поток ADO средствами VBScript
            Скрипт.Eval("Stream.Write(WinHttp.ResponseBody)");
            
            // Сохраняем поток в файл на диске (значение 2 означает перезапись файла при его наличии)
            Stream.SaveToFile(ПутьСохранения, 2);
            Stream.Close();
            
            Сообщить("Файл успешно скачан по HTTPS!");
        Иначе
            Сообщить("Сервер вернул ошибку: " + WinHttp.Status + " " + WinHttp.StatusText);
        КонецЕсли;
    Исключение
        Сообщить("Произошла ошибка при скачивании: " + ОписаниеОшибки(), "!");
    КонецПопытки;
КонецПроцедуры

Этот метод является наиболее "чистым", так как не требует установки стороннего софта на компьютер пользователя и работает полностью в оперативной памяти средствами операционной системы Windows.

Решение №2. Использование утилиты curl (самый надежный и современный способ)

Начиная с Windows 10 (сборка 1803) и во всех версиях Windows 11, мощнейшая консольная утилита для работы с сетевыми запросами curl.exe предустановлена в системе по умолчанию. Если ваши пользователи работают на более ранних ОС (например, Windows 7 или Windows Server 2008), вы можете скачать автономный исполняемый файл curl.exe и положить его в каталог базы данных 1С.

Преимущества использования curl:

Проанализируем программный код вызова утилиты из 1С 7.7:


Процедура СкачатьЧерезCurl(АдресРесурса, ПутьСохранения)
    // Формируем параметры запуска утилиты:
    // -k (или --insecure) - позволяет игнорировать возможные проблемы с цепочкой сертификатов SSL
    // -L (или --location) - заставляет curl автоматически переходить по редиректам (ошибка 301)
    // -o - указывает путь к файлу, куда сохранить результат
    
    Команда = "curl.exe -k -L -o """ + ПутьСохранения + """ """ + АдресРесурса + """";
    
    // Запускаем процесс в скрытом режиме (окно консоли не будет моргать перед пользователем)
    // Третий параметр "1" означает, что 1С будет ожидать завершения работы curl перед выполнением следующего шага
    ЗапуститьПриложение(Команда, , 1);
    
    // Проверяем результат выполнения операции
    Если ФС.СуществуетФайл(ПутьСохранения) = 1 Тогда
        Сообщить("Файл успешно загружен через curl!");
    Иначе
        Сообщить("Ошибка: файл не был загружен. Проверьте адрес ресурса.", "!");
    КонецЕсли;
КонецПроцедуры

Решение №3. Использование PowerShell (без внешних файлов)

Если на компьютерах установлена современная ОС Windows, но вы не хотите использовать сторонние утилиты, можно обратиться к возможностям платформы .NET Framework через оболочку PowerShell, которая присутствует во всех современных дистрибутивах Windows.

Разберем пример кода, принудительно устанавливающего протокол шифрования TLS 1.2 перед началом скачивания:


Процедура СкачатьЧерезPowerShell(АдресРесурса, ПутьСохранения)
    // Формируем команду PowerShell, которая:
    // 1. Явно включает поддержку TLS 1.2 в текущей сессии .NET
    // 2. Инициирует загрузку файла методом DownloadFile класса WebClient
    КомандаPS = "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; " + 
                "(New-Object System.Net.WebClient).DownloadFile('" + АдресРесурса + "', '" + ПутьСохранения + "')";
    
    // Оформляем запуск PowerShell в скрытом режиме
    КомандаЗапуска = "powershell -WindowStyle Hidden -Command """ + КомандаPS + """";
    
    ЗапуститьПриложение(КомандаЗапуска, , 1);
    
    Если ФС.СуществуетФайл(ПутьСохранения) = 1 Тогда
         Сообщить("Файл успешно загружен средствами PowerShell!");
    Иначе
         Сообщить("Не удалось скачать файл через PowerShell.", "!");
    КонецЕсли;
КонецПроцедуры

Решение №4. Настройка локального прокси-туннеля через stunnel

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

Мы можем использовать бесплатную утилиту stunnel. Принцип ее работы заключается в создании локального "моста":

  1. Программа stunnel запускается как служба на компьютере с 1С и начинает слушать определенный локальный порт (например, 11080).
  2. Когда 1С обращается по обычному, незащищенному протоколу HTTP к адресу http://127.0.0.1:11080/, служба принимает этот запрос.
  3. stunnel самостоятельно оборачивает полученный трафик в шифрованный SSL/TLS-пакет и отправляет его на реальный веб-сервер (например, Центрального банка или таможни) по защищенному протоколу HTTPS (порт 443).
  4. Ответ сервера расшифровывается утилитой и возвращается в 1С в чистом HTTP-виде.

Для настройки такой схемы выполните следующие действия:

  1. Скачайте и установите программу stunnel на рабочую станцию или сервер с 1С.
  2. Откройте конфигурационный файл stunnel.conf и внесите в него следующие настройки для целевого сайта (в качестве примера возьмем сайт курсов валют):
    
    [site-https]
    client = yes
    accept = 127.0.0.1:11080
    connect = www.nbrb.by:443
    verifyChain = no
    
  3. Запустите службу stunnel.
  4. В коде 1С 7.7 замените строку запроса. Вместо прямого обращения к сайту направьте запрос на локальный адрес:
    
    // Было: "https://www.nbrb.by/Services/XmlExRates.aspx"
    // Стало:
    АдресРесурса = "http://127.0.0.1:11080/Services/XmlExRates.aspx";
    // Теперь вы можете использовать стандартный HTTP-клиент, и v7plus отработает без ошибок!
    

Важный нюанс: Многие современные веб-серверы анализируют заголовок запроса Host, чтобы определить, к какому именно сайту обращается клиент (если на одном IP-адресе хостится несколько доменов). При отправке запроса на 127.0.0.1 сервер может вернуть ошибку. В этом случае потребуется перенаправить DNS-запросы. Для этого в файле C:\Windows\system32\drivers\etc\hosts прописывают строчку:

www.nbrb.by 127.0.0.1

А в настройках самого stunnel указывают стандартный порт 80 в параметре accept и реальный IP-адрес сервера в параметре connect. Тогда 1С будет обращаться по обычному имени сайта на порт 80, трафик автоматически перехватится локальной утилитой и уйдет на сервер в зашифрованном виде на порт 443.

Важное системное примечание для старых ОС

Если вы решили использовать Решение №1 (компонент WinHttp) на операционных системах семейства Windows Server 2008 R2 или Windows 7, вы все равно можете столкнуться с ошибкой установления защищенного соединения. Это происходит из-за того, что в старых операционных системах протокол TLS 1.2 по умолчанию отключен для системных библиотек WinHTTP.

Для решения этой проблемы необходимо внести изменения в системный реестр Windows:

  1. Перейдите в ветку реестра: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp\ (для 64-битных систем также продублируйте действия в ветке Wow6432Node).
  2. Создайте параметр типа DWORD (32 бита) с именем DefaultSecureProtocols.
  3. Установите значение 0x00000800 (включает поддержку TLS 1.2) или 0x00000A00 (включает TLS 1.1 и TLS 1.2 одновременно).
  4. Перезагрузите компьютер для применения изменений.

Мы подробно проанализировали причины неработоспособности старых веб-компонент 1С 7.7 с шифрованным трафиком и разобрали четыре эффективных практических решения. Выбирайте вариант, наиболее подходящий под инфраструктуру вашей компании: элегантный скрипт-контроль с WinHttp для чистой работы в коде, консольный curl для стабильности, PowerShell для быстрого развертывания или туннелирование через stunnel для работы без изменения конфигурации 1С.

← На главную