Как скачать и сохранить файл по ссылке HTTP/HTTPS в 1С 7.7: обход ошибки «Тип переменной не поддерживается»

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

В процессе интеграции 1С 7.7 с интернет-магазинами, внешними веб-сервисами и API-интерфейсами разработчики часто сталкиваются с необходимостью автоматической загрузки файлов (например, изображений товаров, прайс-листов или XML-файлов) по прямым ссылкам. Если в современных версиях платформы 1С 8.x эта задача решается буквально парой строк кода, то в устаревшей, но все еще активно используемой платформе 1С 7.7 разработчики упираются в серьезные архитектурные ограничения.

В этой статье мы подробно разберем, почему возникает популярная ошибка «Тип переменной не поддерживается» при попытке сохранить бинарные данные через ADODB.Stream, проанализируем причины этого поведения и рассмотрим несколько эффективных способов решения проблемы — как с использованием скриптовых оберток, так и с помощью современных системных утилит Windows.

Выясняем причину: почему стандартный код выдает ошибку?

Типичная попытка скачать файл напрямую через COM-объекты в 1С 7.7 выглядит следующим образом:


WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("GET", "http://www.domain.ru/image.jpg", 0);
WinHttp.Send();

Если WinHttp.Status = 200 Тогда
    Stream = СоздатьОбъект("ADODB.Stream");
    Stream.Type = 1; // adTypeBinary
    Stream.Mode = 3; // adModeReadWrite
    Stream.Open();
    Stream.Write(WinHttp.responseBody); // <-- Здесь происходит падение!
    Stream.SaveToFile("C:\image.jpg", 2);
    Stream.Close();
КонецЕсли;

При выполнении этого кода на строке Stream.Write(WinHttp.responseBody) платформа 1С 7.7 выдает ошибку: «Тип переменной не поддерживается». Почему это происходит?

Дело в том, что свойство responseBody OLE-объекта WinHttpRequest возвращает массив бинарных данных в формате SafeArray (VT_UI1 | VT_ARRAY). Встроенный язык 1С 7.7, разработанный в конце 1990-х годов, изначально не имеет нативной поддержки этого типа данных на уровне своего ядра. Платформа просто не может передать этот массив из одного COM-объекта (WinHttp) в другой (ADODB.Stream) напрямую, поскольку «спотыкается» на этапе преобразования типов во внутренние переменные среды выполнения.

Ниже мы подробно разберем четыре практических метода, которые помогут обойти это ограничение и настроить стабильную загрузку файлов.


Способ 1. Использование MSScriptControl и VBScript (Рекомендуемый COM-метод)

Самый простой способ «подружить» 1С 7.7 с бинарными массивами без использования сторонних внешних компонент — это делегировать операцию записи файла промежуточному скриптовому движку MSScriptControl.ScriptControl с языком VBScript.

Среда выполнения VBScript прекрасно справляется с типом SafeArray и может безболезненно передать данные из WinHttpRequest.responseBody в метод Stream.Write. Давайте разберем готовый шаблон функции:


// Функция скачивает файл по ссылке и сохраняет его на диск
Процедура СкачатьФайлVBS(Знач Ссылка, Знач ПутьСохранения)
    
    // Создаем объект для HTTP-запроса
    Попытка
        WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
    Исключение
        Предупреждение("Не удалось создать объект WinHttp.WinHttpRequest.5.1!");
        Возврат;
    КонецПопытки;
    
    // Отправляем GET-запрос (третий параметр "0" означает синхронный режим)
    WinHttp.Open("GET", Ссылка, 0);
    WinHttp.Send();
    
    Если WinHttp.Status = 200 Тогда
        // Создаем скрипт-контрол для обхода ограничения SafeArray
        Попытка
            Scr = СоздатьОбъект("MSScriptControl.ScriptControl");
            Scr.Language = "vbscript";
        Исключение
            Предупреждение("Не удалось запустить MSScriptControl!");
            Возврат;
        КонецПопытки;
        
        // Формируем текст процедуры на языке VBScript
        ТекстМодуля = "
        |Sub SaveToFile(ByRef FileName, ByRef WinHttp)
        |    Set Stream = CreateObject(""ADODB.Stream"")
        |    Stream.Type = 1 ' adTypeBinary
        |    Stream.Mode = 3 ' adModeReadWrite
        |    Stream.Open
        |    Stream.Write WinHttp.responseBody
        |    Stream.SaveToFile FileName, 2 ' adSaveCreateOverWrite
        |    Stream.Close
        |End Sub";
        
        // Добавляем код в контейнер скрипта и выполняем его
        Scr.AddCode(ТекстМодуля);
        Scr.Run("SaveToFile", ПутьСохранения, WinHttp);
        
        Сообщить("Файл успешно сохранен: " + ПутьСохранения);
    Иначе
        Сообщить("Ошибка загрузки! Код ответа сервера: " + WinHttp.Status + " " + WinHttp.StatusText, "!");
    КонецЕсли;

КонецПроцедуры

Преимущества метода: Работает «из коробки» на большинстве версий Windows, не требует регистрации дополнительных библиотек в системе, корректно обрабатывает протокол HTTPS.


Способ 2. Использование MSScriptControl и JScript

В качестве альтернативы VBScript мы можем задействовать движок JScript (реализация ECMAScript от Microsoft). Принцип работы здесь аналогичен, однако вместо передачи всего COM-объекта в функцию мы связываем объекты 1С с пространством имен скрипта через метод addObject.

Рассмотрим по шагам реализацию этого механизма:


Процедура СкачатьФайлJScript(Знач Ссылка, Знач ПутьСохранения)
    
    Попытка
        WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
        Stream  = СоздатьОбъект("ADODB.Stream");
        Script  = СоздатьОбъект("ScriptControl");
    Исключение
        Сообщить("Ошибка инициализации COM-объектов: " + ОписаниеОшибки(), "!");
        Возврат;
    КонецПопытки;
    
    // Настраиваем поток данных
    Stream.Type = 1; // adTypeBinary
    Stream.Open();
    
    // Настраиваем скрипт-интерпретатор
    Script.Language = "jscript";
    Script.AddObject("WinHttp", WinHttp);
    Script.AddObject("Stream", Stream);
    
    // Выполняем запрос к серверу
    WinHttp.Open("GET", Ссылка, 0);
    WinHttp.Send();
    
    Если WinHttp.Status = 200 Тогда
        // Выполняем бинарную запись средствами JScript
        Script.Eval("Stream.Write(WinHttp.responseBody);");
        
        // Сохраняем файл на диск средствами 1С (объект Stream нам доступен)
        Stream.SaveToFile(ПутьСохранения, 2);
        Stream.Close();
        Сообщить("Файл сохранен: " + ПутьСохранения);
    Иначе
        Сообщить("Сервер вернул код: " + WinHttp.Status, "!");
        Stream.Close();
    КонецЕсли;
    
КонецПроцедуры

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


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

Если ваши рабочие станции или сервер, где выполняется база 1С 7.7, работают под управлением актуальных версий операционных систем (Windows 10 версии 1803 и выше, Windows 11 или современные Windows Server), вам вообще не нужно использовать COM-объекты ActiveX и ScriptControl.

В современные дистрибутивы Windows по умолчанию встроена мощная консольная утилита curl.exe. С ее помощью можно скачать любой файл по защищенному протоколу HTTPS одной строчкой кода. При этом полностью исключаются проблемы утечки памяти и несовместимости типов данных платформы 1С.

Проанализируем пример кода:


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

Если встроенный curl.exe отсутствует (например, на старых ОС Windows Server 2008 R2 / Windows 7), аналогичную операцию можно выполнить через системную оболочку PowerShell, которая гарантированно присутствует во всех ОС, начиная с Windows 7:


Процедура СкачатьЧерезPowerShell(Знач Ссылка, Знач ПутьСохранения)
    
    Команда = "powershell -Command ""Invoke-WebRequest -Uri '" + Ссылка + "' -OutFile '" + ПутьСохранения + "'""";
    КомандаСистемы(Команда);
    
    Если ФС.СуществуетФайл(ПутьСохранения) = 1 Тогда
        Сообщить("Файл успешно скачан через PowerShell!");
    Иначе
        Сообщить("Ошибка при скачивании через PowerShell.", "!");
    КонецЕсли;
    
КонецПроцедуры

Сравнительный анализ методов и важные технические нюансы

При выборе архитектурного решения для вашей задачи обязательно учитывайте следующие важные факторы:

  1. Ограничения MSScriptControl по размеру файлов: Если вам требуется скачивать исключительно небольшие изображения товаров (до 1-2 МБ), методы со ScriptControl работают превосходно. Однако при попытке скачать файлы большого объема (например, базы данных, тяжелые ZIP-архивы или видеофайлы размером более 10 МБ) среда выполнения скриптов может вызвать критическое переполнение памяти, что приведет к аварийному завершению работы (вылету) платформы 1С:Предприятие 7.7. Для больших файлов настоятельно рекомендуется использовать метод с curl.exe.
  2. Проблемы с протоколами безопасности TLS в устаревших ОС: Если база 1С 7.7 крутится на старых серверах под управлением Windows Server 2003 или Windows XP, системные библиотеки WinHttp.WinHttpRequest.5.1 не смогут установить защищенное соединение по протоколам TLS 1.2 или TLS 1.3 (которые сейчас используются практически на всех современных сайтах). В этой ситуации COM-объекты будут выдавать ошибки рукопожатия SSL (Handshake failed). Решить проблему можно установкой внешних консольных утилит (актуальной версии curl) или обновлением корневых сертификатов операционной системы.
  3. Внешние компоненты (Альтернатива): Если в вашей базе активно используется легендарная библиотека 1С++ (1cpp.dll), вы можете задействовать ее внутренний класс ДвоичныеДанные. Он умеет корректно перехватывать и сохранять COM SafeArray без привлечения сторонних VBScript-скриптов. Также хорошим решением является специализированная библиотека curl1c.dll («Карлик»), созданная сообществом разработчиков специально для работы с веб-запросами из среды 1С 7.7.

Резюмируем: Для быстрой и простой загрузки картинок номенклатуры используйте связку MSScriptControl + VBScript (Способ 1). Если же требуется надежность, высокая скорость и работа с большими объемами данных по протоколам HTTPS — смело внедряйте системный вызов утилиты curl (Способ 3).

← На главную