При работе с современными мобильными приложениями или веб-сервисами программисты 1С 7.7 часто сталкиваются с необходимостью обработки данных в формате Base64. Типичная ситуация: планшет передает фотографию в виде длинной текстовой строки, которую необходимо превратить в файл .jpg для последующего вывода на печать или хранения в базе данных. Однако здесь мы натыкаемся на фундаментальное ограничение старой платформы «1С:Предприятие 7.7».
В этой статье мы подробно разберем, почему штатные средства 1С 7.7 не позволяют решить задачу «в лоб», и проанализируем несколько надежных способов обхода этих ограничений.
Разберем ситуацию: формат Base64 — это текстовое представление бинарных данных. Чтобы получить из него картинку, строку нужно декодировать в массив байтов. Главная проблема заключается в том, что движок 1С 7.7 работает со строками как с C-style строками, где символ с кодом 0 (null-terminator) является признаком окончания строки. Бинарный файл изображения (JPG) практически всегда содержит байты с кодом 0. Как только 1С встречает такой символ в строковой переменной, она «считает», что строка закончилась, и при попытке записи в файл данные обрезаются.
Именно поэтому мы не можем просто использовать функцию Текст.ДобавитьСтроку() или объект ФС для записи бинарных данных. Нам требуются инструменты, которые умеют работать с памятью напрямую или через посредников (COM-объекты).
Это, пожалуй, самый элегантный и «родной» для разработчика 1С 7.7 способ. Если в вашей конфигурации используется библиотека 1cpp.dll, задача решается буквально несколькими строками кода. Объект BinaryData специально спроектирован для работы с двоичными данными в обход строковых ограничений платформы.
Проанализируем пример кода:
// Создаем объект из компоненты 1CPP
Попытка
БинарныеДанные = СоздатьОбъект("BinaryData");
Исключение
Предупреждение("Компонента 1CPP не загружена!");
Возврат;
КонецПопытки;
// Предположим, что СтрBase64 - это наша исходная строка
// Декодируем Base64 и сразу записываем в файл на диске
ПутьКФайлу = "C:\Temp\image.jpg";
БинарныеДанные.ИзBase64(СтрBase64);
БинарныеДанные.ЗаписатьВФайл(ПутьКФайлу);
В данном примере метод ИзBase64 выполняет всю тяжелую работу по декодированию, а метод ЗаписатьВФайл корректно сохраняет результат, не опасаясь нулевых байтов. Это самый быстрый способ с точки зрения производительности.
Если вы не можете или не хотите регистрировать сторонние .dll в системе, можно воспользоваться стандартными средствами Windows, доступными через COM-соединение. Мы задействуем связку из MSXML2.DOMDocument (для декодирования текста) и ADODB.Stream (для записи бинарного потока).
Рассмотрим пошагово, как это реализовать:
bin.base64.ADODB.Stream, который умеет сохранять «сырые» данные на диск.Пример программного кода:
Процедура СохранитьКартинкуИзBase64(ТекстBase64, ПутьКФайлу)
// 1. Декодирование через MSXML
xml = СоздатьОбъект("MSXML2.DOMDocument");
Элемент = xml.createElement("Base64Data");
Элемент.dataType = "bin.base64";
Элемент.text = ТекстBase64;
// Получаем массив байтов (SafeArray)
Данные = Элемент.nodeTypedValue;
// 2. Запись через ADODB.Stream
Поток = СоздатьОбъект("ADODB.Stream");
Поток.Type = 1; // adTypeBinary (бинарный режим)
Поток.Open();
Поток.Write(Данные);
Поток.SaveToFile(ПутьКФайлу, 2); // 2 - adSaveCreateOverWrite (перезаписать, если существует)
Поток.Close();
КонецПроцедуры
Этот метод крайне надежен, так как использует системные библиотеки, которые гарантированно присутствуют в Windows начиная с версии XP.
Выясним еще один интересный способ, который часто незаслуженно забывают. В составе Windows есть консольная утилита certutil, которая умеет работать с кодировками. Мы можем сохранить строку Base64 в обычный текстовый файл, а затем вызвать команду системы для его декодирования.
Разберем последовательность действий:
input.txt штатными средствами 1С (объект Текст).certutil -decode input.txt output.jpg.Пример реализации через КомандаСистемы:
Т = СоздатьОбъект("Текст");
Т.ДобавитьСтроку(СтрBase64);
Т.Записать("C:\temp\base64.txt");
// Вызываем системную утилиту в скрытом режиме
Команда = "certutil -decode ""C:\temp\base64.txt"" ""C:\temp\result.jpg""";
КомандаСистемы(Команда);
Важный нюанс: Утилита certutil ожидает, что файл Base64 может содержать заголовки сертификатов. Если декодирование не срабатывает, убедитесь, что в строке нет лишних пробелов или переносов строк, которые 1С может добавлять при записи текстового файла.
После того как мы успешно сохранили файл .jpg на диск одним из вышеперечисленных способов, нам нужно показать его пользователю или распечатать. В 1С 7.7 это делается следующим образом:
ФотоПланшета).В программном коде перед выводом секции на печать выполните загрузку файла:
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("ПечатьФото");
// ... формирование строк ...
Картинка = Таб.ТекущийОбъект; // Обращаемся к объекту рисунка в таблице
Картинка.Загрузить("C:\temp\result.jpg");
Таб.ВывестиСекцию("Данные");
Таб.Показать();
Проанализируем ситуацию с памятью. Строки в формате Base64 примерно на 33% объемнее оригинального файла. Если картинка с планшета имеет высокое разрешение, строка может занимать несколько мегабайт. При передаче таких строк между функциями в 1С 7.7 старайтесь использовать передачу по ссылке, а не по значению, чтобы избежать лишнего копирования данных в оперативной памяти.
Также помните, что 1С 7.7 лучше всего работает со стандартными Baseline JPEG. Если после конвертации картинка отображается черным квадратом или не загружается, проблема может быть в специфическом сжатии (например, Progressive JPEG), которое старый движок платформы не поддерживает. В таком случае может потребоваться промежуточная конвертация через GDI+ или внешние утилиты изменения размера (ImageMagick).
Таким образом, несмотря на почтенный возраст платформы, задача сохранения Base64 в JPG решается вполне успешно. Оптимальным выбором будет использование 1CPP (если компонента уже есть в проекте) или ADODB.Stream (для «чистых» систем).