Как декодировать нестандартную Base64 строку с символами "~", "-" и "_" в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Иногда при разработке интеграций со сторонними веб-сервисами, сайтами или мобильными приложениями мы сталкиваемся с проблемой: платформа 1С не может раскодировать входящую строку Base64. Встроенная функция Base64Значение() вместо двоичных данных упрямо возвращает Неопределено. Проанализируем эту ситуацию и разберем по шагам, почему так происходит и как научить 1С читать такие данные.

Выясним причину: почему функция Base64Значение() возвращает Неопределено

Давайте посмотрим на пример строки, которая вызывает ошибку: 03TG4zS029i~. Если присмотреться, в ней присутствует символ "~" (тильда), а в более длинных строках могут встречаться символы "-" (дефис) и "_" (подчеркивание). Стандартный алфавит алгоритма кодирования Base64 использует латинские буквы, цифры, а также символы "+" и "/". Для выравнивания (кратности длины строки 4) в конце добавляется знак "=".

Рассмотрим подробнее, откуда берутся нестандартные символы. Дело в том, что стандартный Base64 плохо подходит для передачи данных в URL-адресах (например, при GET-запросах вида ?id=base64string). Символы "+" и "/" интерпретируются браузерами и серверами как пробел и разделитель директорий соответственно, а знак "=" зарезервирован для присвоения значений параметрам. Чтобы закодированная строка не ломала структуру веб-адреса, разработчики применяют модификацию алгоритма, известную как URL-safe Base64 (согласно стандарту RFC 4648).

В этой модификации происходят следующие замены:

  1. Символ "+" заменяется на "-".
  2. Символ "/" заменяется на "_".
  3. Символ "=" (знак заполнения) либо отбрасывается вовсе, либо заменяется на безопасный символ, такой как "~" (тильда) или точка.

В версиях платформы 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С отказывается их читать, всегда выполняйте предварительную очистку текста с помощью функции СтрЗаменить() и проверяйте строку на кратность четырем.

← На главную