Как сформировать корректное имя файла из Base64-кодированной строки в 1С?

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

При интеграции систем 1С:Предприятие с внешними веб-сервисами, мобильными приложениями или FTP-серверами разработчики часто сталкиваются с необходимостью передачи файлов, имена которых содержат кириллицу, спецсимволы или пробелы. Поскольку многие операционные системы (особенно семейства Linux, на которых часто работают FTP-серверы) некорректно обрабатывают отличную от UTF-8 кодировку в путях файлов, стандартным решением становится кодирование имени файла в Base64. Этот алгоритм преобразует любые бинарные данные и символы в безопасный набор ASCII-символов.

Однако на практике при попытке присвоить файлу имя, закодированное в Base64, разработчики сталкиваются с рядом технических сложностей. В этой статье мы подробно рассмотрим, почему стандартная строка Base64 ломает файловую систему, как правильно очистить строку от переносов, обойти ограничения платформы 1С старых версий (например, в УТ 10.3) и заменить запрещенные символы.

Почему стандартная строка Base64 не подходит для имени файла?

Алгоритм кодирования Base64 преобразует каждые 3 байта исходных данных в 4 текстовых символа. Согласно спецификации (например, RFC 2045), для удобства чтения текстового потока в результирующую строку автоматически вставляются символы переноса строки каждые 72 или 76 символов. Платформенный метод 1С Base64Строка() работает в строгом соответствии с этими стандартами.

Если исходная строка (например, длинное наименование номенклатуры или контрагента с реквизитами документа) превышает определенную длину, на выходе мы получаем многострочный текст. Символы возврата каретки и перевода строки категорически запрещены в именах файлов операционными системами Windows и Linux. Попытка записать файл с таким именем неизбежно вызовет системную ошибку доступа или создания файла.

Шаг 1. Очистка строки от переносов (CR/LF)

Для решения этой проблемы нам необходимо удалить управляющие спецсимволы. Разберем по шагам, как это сделать наиболее надежным способом. В платформе 1С для этого используются глобальные переменные Символы.ВК (возврат каретки, CR) и Символы.ПС (перевод строки, LF).

Важно производить замену этих символов последовательно, а не одной комбинированной строкой. На разных операционных системах перенос строки может кодироваться по-разному (в Windows это пара CR+LF, в Unix-системах только LF, в старых macOS только CR). Последовательная замена гарантирует полную очистку в любой среде.

Посмотрим на пример кода, реализующий безопасную очистку:


// Функция удаляет все управляющие символы переноса строки из кодированной строки
Функция ОчиститьСтрокуBase64ОтПереносов(ИсходнаяСтрокаBase64) Экспорт
    Результат = ИсходнаяСтрокаBase64;
    
    // Удаляем возврат каретки (CR)
    Результат = СтрЗаменить(Результат, Символы.ВК, "");
    
    // Удаляем перевод строки (LF)
    Результат = СтрЗаменить(Результат, Символы.ПС, "");
    
    Возврат Результат;
КонецФункции

Шаг 2. Замена запрещенных символов (Модифицированный Base64URL)

Очистка от переносов строк — это лишь половина дела. Стандартный алфавит Base64 включает в себя символы + (плюс), / (прямой слеш) и = (знак равенства, используемый для выравнивания длины строки). Эти символы несут в себе опасность при работе с файловыми системами и сетевыми протоколами:

Чтобы решить эту проблему, мы реализуем стандарт Base64URL, адаптированный для файловых систем. Для этого заменим небезопасные символы на разрешенные:

Проанализируем пример кода для адаптации строки Base64 под имя файла:


Функция ПолучитьБезопасноеИмяФайлаBase64(ИсходнаяСтрока) Экспорт
    // Сначала получаем стандартный Base64
    СтрокаBase64 = ПолучитьBase64ИзСтрокиСовместимо(ИсходнаяСтрока);
    
    // Очищаем от переносов строк
    СтрокаBase64 = ОчиститьСтрокуBase64ОтПереносов(СтрокаBase64);
    
    // Производим замену запрещенных в именах файлов символов
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, "/", "_");
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, "+", "-");
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, "=", "");
    
    Возврат СтрокаBase64;
КонецФункции

Шаг 3. Обеспечение совместимости со старыми платформами (УТ 10.3)

Конфигурация «Управление торговлей, редакция 10.3» изначально разрабатывалась под старые версии платформы 1С:Предприятие 8.1 и 8.2 (или запускается в режиме совместимости на 8.3). В этих версиях отсутствует встроенная функция ПолучитьДвоичныеДанныеИзСтроки().

Если мы попытаемся вызвать Base64Строка() напрямую от обычной текстовой строки, платформа выдаст ошибку, так как этот метод принимает исключительно объект типа ДвоичныеДанные. Нам нужно сначала преобразовать текст в двоичные данные.

Рассмотрим надежный способ обхода этого ограничения через временный файл на диске. Это самый простой кроссплатформенный метод, который работает абсолютно на любой версии 1С. Мы записываем исходную строку во временный файл в кодировке UTF-8 с помощью объекта ЗаписьТекста, а затем читаем этот файл как ДвоичныеДанные.

Ниже представлен код функции, которая корректно получает Base64-строку с учетом совместимости платформ:


Функция ПолучитьBase64ИзСтрокиСовместимо(ИсходнаяСтрока) 
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
    
    // Записываем текст в файл в кодировке UTF-8 без BOM
    ТекстовыйФайл = Новый ЗаписьТекста(ИмяВременногоФайла, КодировкаТекста.UTF8, , , Ложь);
    ТекстовыйФайл.Записать(ИсходнаяСтрока);
    ТекстовыйФайл.Закрыть();
    
    // Читаем файл в двоичные данные
    ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ИмяВременногоФайла);
    
    // Получаем строку Base64
    СтрокаBase64 = Base64Строка(ДвоичныеДанныеФайла);
    
    // Удаляем временный файл
    Попытка
        УдалитьФайлы(ИмяВременногоФайла);
    Исключение
        // Ошибка удаления не должна прерывать работу алгоритма
    КонецПопытки;
    
    Возврат СтрокаBase64;
КонецФункции

Шаг 4. Обратное декодирование имени файла

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

  1. Восстановление оригинального алфавита Base64 (обратная замена символов _ на / и - на +).
  2. Восстановление знаков равенства = в конце строки. Длина валидной Base64-строки всегда должна быть кратна 4. Нам нужно вычислить остаток от деления длины строки на 4 и дописать недостающие знаки равенства.
  3. Преобразование очищенной Base64-строки в двоичные данные с помощью Base64Значение() и последующее чтение текста.

Рассмотрим детальный пример функции декодирования:


Функция ДекодироватьИмяФайлаИзBase64(БезопасноеИмяBase64) Экспорт
    // 1. Возвращаем оригинальные символы алфавита
    СтрокаBase64 = СтрЗаменить(БезопасноеИмяBase64, "_", "/");
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, "-", "+");
    
    // 2. Математически восстанавливаем знаки "=" до кратности длины 4
    Остаток = СтрДлина(СтрокаBase64) % 4;
    Если Остаток > 0 Тогда
        СтрокаBase64 = СтрокаBase64 + Лев("====", 4 - Остаток);
    КонецЕсли;
    
    // 3. Декодируем в двоичные данные
    Попытка
        ДвоичныеДанные = Base64Значение(СтрокаBase64);
    Исключение
        ЗаписьЖурналаРегистрации("Декодирование файла", УровеньЖурналаРегистрации.Ошибка, , , 
            "Не удалось декодировать строку из Base64: " + ОписаниеОшибки());
        Возврат "";
    КонецПопытки;
    
    // 4. Записываем двоичные данные во временный файл и считываем текст
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
    ДвоичныеДанные.Записать(ИмяВременногоФайла);
    
    ТекстовыйФайл = Новый ЧтениеТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
    ИсходноеИмя = ТекстовыйФайл.Прочитать();
    ТекстовыйФайл.Закрыть();
    
    УдалитьФайлы(ИмяВременногоФайла);
    
    Возврат ИсходноеИмя;
КонецФункции

Альтернативный вариант: Хеширование имен файлов

Важно помнить, что кодирование в Base64 увеличивает объем исходной строки примерно на 33%. Большинство операционных систем и FTP-серверов имеют жесткое ограничение на длину имени одного файла — не более 255 символов. Если исходное имя исходного документа очень длинное, то закодированное в Base64 имя может превысить этот лимит, что сделает невозможным сохранение файла.

Если перед вами стоит задача сделать уникальные, безопасные имена файлов для передачи на FTP, а расшифровка имени принимающей стороной "на лету" не требуется, рассмотрите альтернативу в виде хеширования (алгоритмы MD5 или SHA-256).

Преимущества хеширования:

Связь между реальным именем файла и его хешем в таком сценарии передается принимающей стороне в отдельном небольшом файле-манифесте (например, в формате XML или JSON).

← На главную