Как в 1С 7.7 декодировать большой файл из Base64, чтобы программа не «падала»?

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

При работе в среде 1С:Предприятие 7.7 разработчики часто сталкиваются с аппаратными и программными ограничениями платформы, которая создавалась еще в те времена, когда файлы размером в несколько мегабайт считались огромными. Одна из классических проблем — падение или критическая ошибка системы при попытке передать длинную строку (Base64-код) в свойство COM-объекта (например, MSXML2.DOMDocument). Рассмотрим, почему это происходит и какими способами можно декодировать большие файлы без сбоев.

Почему 1С 7.7 падает на больших строках?

Проанализируем ситуацию: при использовании стандартных объектов Windows, таких как ADODB.Stream для чтения файла и MSXML2.DOMDocument для декодирования Base64, код часто выглядит следующим образом:


objDocElem.text = base64text; // Здесь происходит падение

Выясним причину: в 1С 7.7 реализация работы с COM-объектами (IDispatch) имеет внутреннее ограничение на длину передаваемой строки. Как только размер файла Base64 превышает 256–300 КБ, попытка присвоить значение свойству .text напрямую приводит к переполнению буфера или некорректной работе с памятью, из-за чего 1С завершает работу без объяснения причин.

Решение 1: Использование внешней компоненты OLEExSup.dll

Самый эффективный способ обойти ограничение — использовать специальную компоненту-помощник OLEExSup.dll. Она позволяет вызывать методы и устанавливать свойства OLE-объектов напрямую, минуя стандартный механизм 1С. Разберем по шагам, как модифицировать функцию декодирования.

1. Загрузка компоненты и создание объектов:


ЗагрузитьВнешнююКомпоненту("OLEExSup.dll");
ОлеЭксуп = СоздатьОбъект("OLEExSup");

objXML = СоздатьОбъект("MSXml2.DOMDocument");
objDocElem = objXML.createElement("tmp");
objDocElem.DataType = "bin.base64";

2. Чтение файла через поток: Для стабильной работы важно правильно указать кодировку. Если файл содержит Base64, лучше всего использовать "windows-1251" или "ascii".


objStream = СоздатьОбъект("ADODB.Stream");
objStream.Type = 2; // Текстовый
objStream.Charset = "windows-1251";
objStream.Open();
objStream.LoadFromFile(ПутьКФайлуBase64);
base64text = objStream.ReadText();

3. Установка свойства через компоненту: Вместо прямого присваивания objDocElem.text = ..., мы используем метод PutProperty.


ОлеЭксуп.PutProperty(objDocElem, "text", base64text);

После этого данные попадают в объект MSXML без падения системы, и их можно сохранять как двоичный файл через другой ADODB.Stream с типом 1 (binary).

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

Если вы не хотите регистрировать лишние DLL-библиотеки в системе, рассмотрим вариант использования встроенного в Windows инструмента. Программа certutil.exe умеет эффективно работать с кодированием Base64 на уровне операционной системы.

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


// ПутьКВходящемуФайлу - текстовый файл с Base64
// ПутьКВыходящемуФайлу - результат (картинка, PDF и т.д.)
КомандаСистемы("certutil -decode """ + ПутьКВходящемуФайлу + """ """ + ПутьКВыходящемуФайлу + """");

Важный нюанс: Утилита certutil ожидает, что файл Base64 имеет стандартные заголовки (BEGIN/END CERTIFICATE), но прекрасно справляется и без них, если файл содержит только "чистый" Base64-код.

Решение 3: Декодирование внутри ScriptControl

Еще один способ избежать передачи длинной строки между 1С и OLE — перенести всю логику внутрь скриптового движка. Посмотрим на пример реализации через MSScriptControl.ScriptControl:


Scpt = СоздатьОбъект("MSScriptControl.ScriptControl");
Scpt.Language = "VBScript";
// Передаем только пути к файлам — это короткие строки
Scpt.AddCode("
|Function DecodeFile(InPath, OutPath)
|    Set objXML = CreateObject(""MSXml2.DOMDocument"")
|    Set objDocElem = objXML.createElement(""tmp"")
|    objDocElem.DataType = ""bin.base64""
|
|    Set objStreamIn = CreateObject(""ADODB.Stream"")
|    objStreamIn.Open
|    objStreamIn.LoadFromFile InPath
|    objDocElem.text = objStreamIn.ReadText
|
|    Set objStreamOut = CreateObject(""ADODB.Stream"")
|    objStreamOut.Type = 1 'Binary
|    objStreamOut.Open
|    objStreamOut.Write objDocElem.NodeTypedValue
|    objStreamOut.SaveToFile OutPath, 2
|End Function");

Scpt.Run("DecodeFile", ПутьВход, ПутьВыход);

В данном случае вся работа по чтению, декодированию и записи происходит внутри процесса скрипта. 1С лишь инициирует выполнение, передавая два строковых параметра с путями, что полностью исключает риск падения из-за размера данных.

Важные замечания по кодировкам и BOM

Проанализируем возможные ошибки при работе с файлами:

  1. Наличие BOM (Byte Order Mark): Если файл сохранен в кодировке UTF-8 или UTF-16 с меткой BOM (первые несколько байт файла), объект MSXML может выдать ошибку "Неверный формат". Перед обработкой желательно убедиться, что файл сохранен как "UTF-8 without BOM" или обычный ANSI.
  2. Символы переноса строк: Base64-строка в файле может содержать переносы строк (CRLF). Стандартные средства декодирования Windows обычно игнорируют их, но если вы формируете строку вручную, следите за отсутствием лишних пробелов.
  3. Тип стрима: При сохранении результата всегда устанавливайте objStream.Type = 1 (Binary), иначе ADODB.Stream попытается интерпретировать двоичные данные как текст, что приведет к повреждению итогового файла.

Подводя итог, можно сказать: для небольших файлов (до 200 КБ) подходит стандартный метод через MSXML2.DOMDocument. Для файлов среднего размера (до 5–10 МБ) оптимально использовать ScriptControl или OLEExSup.dll. Для промышленной обработки гигабайтных архивов лучшим выбором остается вызов certutil.

← На главную