При работе в среде 1С:Предприятие 7.7 разработчики часто сталкиваются с аппаратными и программными ограничениями платформы, которая создавалась еще в те времена, когда файлы размером в несколько мегабайт считались огромными. Одна из классических проблем — падение или критическая ошибка системы при попытке передать длинную строку (Base64-код) в свойство COM-объекта (например, MSXML2.DOMDocument). Рассмотрим, почему это происходит и какими способами можно декодировать большие файлы без сбоев.
Проанализируем ситуацию: при использовании стандартных объектов Windows, таких как ADODB.Stream для чтения файла и MSXML2.DOMDocument для декодирования Base64, код часто выглядит следующим образом:
objDocElem.text = base64text; // Здесь происходит падение
Выясним причину: в 1С 7.7 реализация работы с COM-объектами (IDispatch) имеет внутреннее ограничение на длину передаваемой строки. Как только размер файла Base64 превышает 256–300 КБ, попытка присвоить значение свойству .text напрямую приводит к переполнению буфера или некорректной работе с памятью, из-за чего 1С завершает работу без объяснения причин.
Самый эффективный способ обойти ограничение — использовать специальную компоненту-помощник 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).
Если вы не хотите регистрировать лишние DLL-библиотеки в системе, рассмотрим вариант использования встроенного в Windows инструмента. Программа certutil.exe умеет эффективно работать с кодированием Base64 на уровне операционной системы.
Этот метод считается самым быстрым и надежным для файлов любого размера (хоть 100 МБ), так как 1С вообще не держит тело файла в своей памяти. Мы просто отдаем команду операционной системе:
// ПутьКВходящемуФайлу - текстовый файл с Base64
// ПутьКВыходящемуФайлу - результат (картинка, PDF и т.д.)
КомандаСистемы("certutil -decode """ + ПутьКВходящемуФайлу + """ """ + ПутьКВыходящемуФайлу + """");
Важный нюанс: Утилита certutil ожидает, что файл Base64 имеет стандартные заголовки (BEGIN/END CERTIFICATE), но прекрасно справляется и без них, если файл содержит только "чистый" Base64-код.
Еще один способ избежать передачи длинной строки между 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С лишь инициирует выполнение, передавая два строковых параметра с путями, что полностью исключает риск падения из-за размера данных.
Проанализируем возможные ошибки при работе с файлами:
MSXML может выдать ошибку "Неверный формат". Перед обработкой желательно убедиться, что файл сохранен как "UTF-8 without BOM" или обычный ANSI.objStream.Type = 1 (Binary), иначе ADODB.Stream попытается интерпретировать двоичные данные как текст, что приведет к повреждению итогового файла.Подводя итог, можно сказать: для небольших файлов (до 200 КБ) подходит стандартный метод через MSXML2.DOMDocument. Для файлов среднего размера (до 5–10 МБ) оптимально использовать ScriptControl или OLEExSup.dll. Для промышленной обработки гигабайтных архивов лучшим выбором остается вызов certutil.