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