Иногда при разработке интеграций со сторонними веб-сервисами, сайтами или мобильными приложениями мы сталкиваемся с проблемой: платформа 1С не может раскодировать входящую строку Base64. Встроенная функция Base64Значение() вместо двоичных данных упрямо возвращает Неопределено. Проанализируем эту ситуацию и разберем по шагам, почему так происходит и как научить 1С читать такие данные.
Давайте посмотрим на пример строки, которая вызывает ошибку: 03TG4zS029i~. Если присмотреться, в ней присутствует символ "~" (тильда), а в более длинных строках могут встречаться символы "-" (дефис) и "_" (подчеркивание). Стандартный алфавит алгоритма кодирования Base64 использует латинские буквы, цифры, а также символы "+" и "/". Для выравнивания (кратности длины строки 4) в конце добавляется знак "=".
Рассмотрим подробнее, откуда берутся нестандартные символы. Дело в том, что стандартный Base64 плохо подходит для передачи данных в URL-адресах (например, при GET-запросах вида ?id=base64string). Символы "+" и "/" интерпретируются браузерами и серверами как пробел и разделитель директорий соответственно, а знак "=" зарезервирован для присвоения значений параметрам. Чтобы закодированная строка не ломала структуру веб-адреса, разработчики применяют модификацию алгоритма, известную как URL-safe Base64 (согласно стандарту RFC 4648).
В этой модификации происходят следующие замены:
В версиях платформы 1С:Предприятие 8.3.15 – 8.3.17 парсер Base64 работает достаточно жестко: встретив неразрешенный символ (например, тильду) или обнаружив некратность строки 4, он просто прекращает работу и возвращает Неопределено. В старых (до 8.3.13) и более новых (начиная с 8.3.18) релизах платформы этот механизм может работать более снисходительно, отбрасывая лишнее, но для надежности нам необходимо явно привести строку к классическому формату.
Чтобы без проблем получить из такой строки ДвоичныеДанные, нам нужно программно обратить те замены, которые сделала внешняя система. Рассмотрим, как это реализовать в рамках кода 1С. Нам понадобятся простые строковые функции для обратной замены символов.
Посмотрим на пример базового решения. Если мы точно знаем, что тильда заменяет знак равенства, алгоритм сводится к трем функциям СтрЗаменить():
Функция ДекодироватьURLSafeBase64(ВходящаяСтрока)
// Заменяем URL-безопасные символы обратно на стандартные
СтандартнаяСтрока = СтрЗаменить(ВходящаяСтрока, "-", "+");
СтандартнаяСтрока = СтрЗаменить(СтандартнаяСтрока, "_", "/");
СтандартнаяСтрока = СтрЗаменить(СтандартнаяСтрока, "~", "=");
// Пытаемся раскодировать
Результат = Base64Значение(СтандартнаяСтрока);
Возврат Результат;
КонецФункции
В некоторых случаях внешняя система не заменяет знаки равенства на тильду, а просто их отбрасывает (обрезает строку). Если мы передадим такую строку в 1С (особенно в определенных релизах платформы), отсутствие кратности длины строки 4 вызовет ошибку. Проанализируем математику Base64: исходные данные кодируются блоками по 3 байта в 4 символа текста. Если символов не хватает, строка дополняется знаками "=".
Мы можем программно вычислить остаток от деления длины строки на 4 и добавить нужное количество знаков равенства в конец строки. Посмотрим на пример кода, реализующий эту логику:
Функция НормализоватьИДекодироватьBase64(ВходящаяСтрока)
// Шаг 1: Замена базовых нестандартных символов
ОбработаннаяСтрока = СтрЗаменить(ВходящаяСтрока, "_", "/");
ОбработаннаяСтрока = СтрЗаменить(ОбработаннаяСтрока, "-", "+");
ОбработаннаяСтрока = СтрЗаменить(ОбработаннаяСтрока, "~", "=");
Данные = Base64Значение(ОбработаннаяСтрока);
// Шаг 2: Если декодировать не удалось, проверяем кратность
Если Данные = Неопределено Тогда
Остаток = СтрДлина(ОбработаннаяСтрока) % 4;
Если Остаток = 1 Тогда
// Ситуация логически невозможна при корректном кодировании
ВызватьИсключение "Неверная входная строка Base64: " + ВходящаяСтрока;
ИначеЕсли Остаток = 2 Тогда
ОбработаннаяСтрока = ОбработаннаяСтрока + "==";
ИначеЕсли Остаток = 3 Тогда
ОбработаннаяСтрока = ОбработаннаяСтрока + "=";
КонецЕсли;
// Повторная попытка
Данные = Base64Значение(ОбработаннаяСтрока);
КонецЕсли;
Возврат Данные;
КонецФункции
Резюме: Внутренние идентификаторы объектов (такие как уникальные идентификаторы GUID) или картинки, передаваемые в формате URL-safe Base64, часто содержат символы-заменители. Если встроенная функция 1С отказывается их читать, всегда выполняйте предварительную очистку текста с помощью функции СтрЗаменить() и проверяйте строку на кратность четырем.