При интеграции систем и передаче файлов через текстовые форматы разработчики часто сталкиваются с кодированием в формат Base64. Нередко возникает ситуация: двоичные данные преобразуются в строку, записываются в текстовый файл или выгружаются в таблицу Microsoft Excel, но при обратном чтении длина строки оказывается совершенно другой. Разберем по шагам, почему так происходит, опасна ли разница в длине для целостности файлов и как правильно работать с такими строками в платформе 1С:Предприятие.
Рассмотрим типовую ситуацию. Исходный файл кодируется в Base64 с помощью встроенной функции платформы 1С:
ДД = Новый ДвоичныеДанные("C:\katalog\temp.png");
Текст64 = Base64Строка(ДД);
Сообщить(СтрДлина(Текст64));
При проверке длины полученной строки мы видим одно число (например, 236 902 символа). Если затем мы сохраняем эту строку в текстовый документ через объект ТекстовыйДокумент и читаем его построчно, длина уменьшается (в примере до 229 724 символов). А если строка выгружалась в ячейку Excel, длина строки после чтения становится ровно 32 767 символов. Выясним причину каждого из этих явлений.
Base64Строка(), а также метод ПолучитьBase64СтрокуИзДвоичныхДанных() формируют строку в соответствии со спецификацией MIME. По этому стандарту непрерывный поток символов Base64 разбивается на строки фиксированной длины — ровно по 64 символа, после чего вставляются невидимые символы перевода строки и возврата каретки (CRLF, то есть Символы.ВК + Символы.ПС). Именно эти служебные пары символов увеличивают общий размер исходной строки на несколько тысяч знаков.ПолучитьСтроку() возвращает строку без завершающих символов перевода строки. Если читать файл в цикле и складывать результат через оператор конкатенации +, все символы CRLF отбрасываются. В результате длина строки становится меньше ровно на количество исключенных служебных символов.Проанализируем важную особенность декодирования: несмотря на то, что строка после чтения из текстового файла потеряла символы переноса, функция обратного преобразования (Base64Значение() или ПолучитьДвоичныеДанныеИзBase64Строки()) корректно восстанавливает исходный файл. Это происходит потому, что алгоритм декодирования Base64 по стандарту полностью игнорирует любые пробельные символы и знаки переноса строк. Таким образом, и строка с переносами строк, и строка без них являются валидными и формируют абсолютно идентичный набор байтов.
Однако с Excel такой трюк не сработает: обрезка до 32 767 символов безвозвратно уничтожает оставшуюся часть файла, поэтому восстановить исходные двоичные данные из одной ячейки невозможно.
Чтобы избежать искажения служебных символов и не тратить ресурсы системы на конкатенацию сотен тысяч строк в цикле, заменим ТекстовыйДокумент на объекты ЗаписьТекста и ЧтениеТекста. Они позволяют работать с текстом как с единым массивом данных.
Запись строки Base64 в файл:
Запись = Новый ЗаписьТекста("C:\katalog\b64.txt", КодировкаТекста.UTF8);
Запись.Записать(Текст64);
Запись.Закрыть();
Чтение файла целиком одной операцией:
Чтение = Новый ЧтениеТекста("C:\katalog\b64.txt", КодировкаТекста.UTF8);
ТекстИзФайла = Чтение.Прочитать();
Чтение.Закрыть();
// Восстановление двоичных данных
ДДВосстановленные = Base64Значение(ТекстИзФайла);
ДДВосстановленные.Записать("C:\katalog\restored.png");
При таком подходе длина строки останется в точности такой же, как при первичном кодировании, а чтение выполнится мгновенно.
Посмотрим на задачу шире: если промежуточный текстовый файл не требуется для передачи через внешние REST- или SOAP-сервисы, преобразовывать файл в Base64 вообще не имеет практического смысла. Платформа 1С позволяет напрямую читать и сохранять двоичные файлы без промежуточного перевода в текст, что экономит память и процессорное время:
// Чтение файла в двоичные данные
Двоичные = Новый ДвоичныеДанные("C:\katalog\temp.png");
// Сохранение двоичных данных в новый файл
Двоичные.Записать("C:\katalog\temp_copy.png");
Если стоит задача передать изображение или большой файл внутрь документа Excel, рассмотрим два правильных сценария обхода лимита в 32 767 знаков:
Эксел = Новый COMОбъект("Excel.Application");
Книга = Эксел.Workbooks.Open("C:\katalog\katalog.xlsx");
Лист = Книга.Sheets(1);
// Параметры: ПутьКФайлу, СвязатьСФайлом, СохранятьСДокументом, Лево, Верх, Ширина, Высота
Лист.Shapes.AddPicture("C:\katalog\temp.png", Ложь, Истина, 50, 50, 200, 150);
Книга.Save();
Эксел.Quit();
Base64Значение().