Как решить проблему с кодировкой кириллицы в именах файлов на FTP в 1С?

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

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

В этой статье мы подробно разберем, почему встроенный механизм FTPСоединение в 1С может искажать кодировку имен файлов, как правильно настроить FTP-сервер для бесконфликтной работы и какие программные обходные пути существуют на стороне платформы 1С.

Почему происходит сбой кодировки: техническая суть конфликта

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

  1. Поведение платформы 1С: Внутри платформы «1С:Предприятие» все строковые переменные хранятся в формате Unicode (UTF-16). Однако при вызове стандартного объекта FTPСоединение под управлением ОС Windows, платформа делегирует работу с сетью системным библиотекам (в частности, WinINet). Эти библиотеки по умолчанию могут транслировать имена файлов в локальную однобайтную кодировку операционной системы — для русскоязычной Windows это Windows-1251 (CP1251).
  2. Поведение FTP-сервера: Большинство современных FTP-серверов работают под управлением операционных систем семейства Linux (например, CentOS, Ubuntu, Debian). В этих системах стандартом по умолчанию является кодировка UTF-8. Когда сервер получает имя файла в кодировке Windows-1251, он записывает его байты «как есть», не производя перекодирования. В результате в файловой системе Linux имя файла выглядит некорректно.
  3. Нарушение протокола RFC 2640: Согласно международным стандартам, для работы с национальными алфавитами FTP-клиент должен согласовать с сервером использование Юникода с помощью команды OPTS UTF8 ON. Встроенный клиент 1С в некоторых версиях платформы выполняет это согласование некорректно либо не выполняет вовсе, из-за чего сервер продолжает ожидать данные в локальной кодировке.

Ситуация усугубляется, если обмен происходит между разными версиями платформ 1С или операционными системами (например, сервер 1С работает на Linux, а клиенты — на Windows), что сразу приводит к рассинхронизации кодировок.

Решение 1: Настройка FTP-сервера (на примере vsftpd на CentOS)

Если у вас или у ваших системных администраторов есть доступ к управлению FTP-сервером, проблему проще всего решить на стороне сервера. Заявление о том, что у FTP-серверов «нет настроек кодировки», ошибочно.

Рассмотрим, как настроить популярный FTP-демон vsftpd на сервере CentOS для автоматической конвертации кодировок «на лету»:

Для этого в конфигурационный файл сервера (обычно он находится по пути /etc/vsftpd/vsftpd.conf) необходимо добавить параметры интеграции с таблицами перекодирования iconv. Внесем следующие директивы:


# Включение модуля конвертации кодировок
convert_charset_enable=YES

# Кодировка, в которой файлы должны храниться на сервере (Linux)
local_charset=UTF8

# Кодировка, которую используют клиенты (Windows-1251)
remote_charset=WIN1251

После внесения изменений обязательно перезапустите службу FTP-сервера командой в консоли Linux:

systemctl restart vsftpd

Что это дает: Теперь сервер будет автоматически переводить имена файлов, приходящие от 1С в кодировке CP1251, в стандартную UTF-8 для хранения на диске. При запросе списка файлов клиентом 1С сервер выполнит обратную конвертацию, и платформа без ошибок прочитает имена файлов.

Решение 2: Программная транслитерация имен файлов в 1С

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

Разберем по шагам пример функции на языке 1С, которая заменяет все русские буквы в имени файла на их латинские аналоги перед отправкой:


Функция ТранслитерироватьИмяФайла(Знач ИсходноеИмя) Экспорт
    
    ТаблицаСоответствия = Новый Соответствие;
    ТаблицаСоответствия.Вставить("а", "a");   ТаблицаСоответствия.Вставить("б", "b");
    ТаблицаСоответствия.Вставить("в", "v");   ТаблицаСоответствия.Вставить("г", "g");
    ТаблицаСоответствия.Вставить("д", "d");   ТаблицаСоответствия.Вставить("е", "e");
    ТаблицаСоответствия.Вставить("ё", "yo");  ТаблицаСоответствия.Вставить("ж", "zh");
    ТаблицаСоответствия.Вставить("з", "z");   ТаблицаСоответствия.Вставить("и", "i");
    ТаблицаСоответствия.Вставить("й", "y");   ТаблицаСоответствия.Вставить("к", "k");
    ТаблицаСоответствия.Вставить("л", "l");   ТаблицаСоответствия.Вставить("м", "m");
    ТаблицаСоответствия.Вставить("н", "n");   ТаблицаСоответствия.Вставить("о", "o");
    ТаблицаСоответствия.Вставить("п", "p");   ТаблицаСоответствия.Вставить("р", "r");
    ТаблицаСоответствия.Вставить("с", "s");   ТаблицаСоответствия.Вставить("т", "t");
    ТаблицаСоответствия.Вставить("у", "u");   ТаблицаСоответствия.Вставить("ф", "f");
    ТаблицаСоответствия.Вставить("х", "kh");  ТаблицаСоответствия.Вставить("ц", "ts");
    ТаблицаСоответствия.Вставить("ч", "ch");  ТаблицаСоответствия.Вставить("ш", "sh");
    ТаблицаСоответствия.Вставить("щ", "sch"); ТаблицаСоответствия.Вставить("ъ", "");
    ТаблицаСоответствия.Вставить("ы", "y");   ТаблицаСоответствия.Вставить("ь", "");
    ТаблицаСоответствия.Вставить("э", "e");   ТаблицаСоответствия.Вставить("ю", "yu");
    ТаблицаСоответствия.Вставить("я", "ya");
    
    // Заполняем заглавные буквы
    Для Каждого КлючЗначение Из ТаблицаСоответствия Цикл
        ТаблицаСоответствия.Вставить(ВРег(КлючЗначение.Ключ), ТРег(КлючЗначение.Значение));
    КонецЦикла;
    
    Результат = "";
    Для Индекс = 1 По СтрДлина(ИсходноеИмя) Цикл
        ТекущийСимвол = Сред(ИсходноеИмя, Индекс, 1);
        ЛатинскийАналог = ТаблицаСоответствия.Получить(ТекущийСимвол);
        Если ЛатинскийАналог <> Неопределено Тогда
            Результат = Результат + ЛатинскийАналог;
        Иначе
            Результат = Результат + ТекущийСимвол;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
    
КонецФункции

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

Решение 3: Отказ от «FTPСоединение» в пользу утилиты WinSCP

Когда стандартный объект платформы 1С FTPСоединение продолжает вести себя нестабильно, разработчики используют внешние специализированные консольные утилиты. Одной из самых надежных является бесплатная утилита WinSCP. Она умеет принудительно работать в UTF-8 и детально настраивать параметры сессии через командную строку.

Рассмотрим пример кода, реализующий выгрузку файла на FTP-сервер с помощью WinSCP и встроенного метода ЗапуститьПриложение():


Процедура ВыгрузитьФайлЧерезWinSCP(ПутьКWinSCP, АдресСервера, Логин, Пароль, ЛокальныйФайл, УдаленныйКаталог)
    
    // Создаем временный файл скрипта для WinSCP
    ИмяФайлаСкрипта = ПолучитьИмяВременногоФайла("txt");
    
    ТекстСкрипта = Новый ТекстовыйДокумент;
    ТекстСкрипта.ДобавитьСтроку("option batch abort");
    ТекстСкрипта.ДобавитьСтроку("option confirm off");
    
    // Открываем соединение с принудительным включением UTF-8
    СтрокаПодключения = СтрШаблон("open ftp://%1:%2@%3/ -rawsettings Utf8=1", Логин, Пароль, АдресСервера);
    ТекстСкрипта.ДобавитьСтроку(СтрокаПодключения);
    
    // Команда перехода в каталог и загрузки файла
    ТекстСкрипта.ДобавитьСтроку(СтрШаблон("cd ""%1""", УдаленныйКаталог));
    ТекстСкрипта.ДобавитьСтроку(СтрШаблон("put ""%1""", ЛокальныйФайл));
    
    ТекстСкрипта.ДобавитьСтроку("close");
    ТекстСкрипта.ДобавитьСтроку("exit");
    
    // Записываем скрипт на диск в ANSI-кодировке
    ТекстСкрипта.Записать(ИмяФайлаСкрипта, КодировкаТекста.ANSI);
    
    // Формируем параметры запуска консольной версии WinSCP (winscp.com)
    ПараметрыЗапуска = СтрШаблон("/script=""%1""", ИмяФайлаСкрипта);
    
    // Запускаем процесс в фоновом режиме с ожиданием завершения
    ЗапуститьПриложение(ПутьКWinSCP + " " + ПараметрыЗапуска, , Истина);
    
    // Удаляем временный файл скрипта
    Попытка
        УдалитьФайлы(ИмяФайлаСкрипта);
    Исключение
        // Обработка исключения при невозможности удалить временный файл
    КонецПопытки;
    
КонецПроцедуры

Использование этого метода гарантирует, что имя файла дойдет до сервера в неизменном UTF-8 виде, независимо от того, на какой операционной системе развернут сервер 1С и какие региональные настройки установлены в ОС Windows.

Особый баг платформы 1С: обрезание имени на символе "@"

Помимо кодировки, при работе с объектом FTPФайл программисты часто сталкиваются со странным поведением: имя файла обрезается, если в нем присутствует символ «собаки» (@).

Выясним причину этого бага. Внутренний синтаксический анализатор (парсер) путей в платформе 1С написан таким образом, что он пытается разбирать переданные строки как URL-адреса. В спецификации URL символ @ является разделителем авторизационных данных пользователя и адреса хоста (например: ftp://логин:пароль@сервер).

Когда парсер 1С натыкается на символ @ внутри имени файла (например, otchet_@_01.xml), он ошибочно считает все, что находится до этого символа, логином и паролем, а остальную часть строки — адресом сервера. В результате имя файла искажается, обрезается, а система выдает ошибку о невозможности найти файл.

Решение проблемы с "@": Единственным надежным решением является полное исключение символа @ из путей и названий файлов при работе через встроенные механизмы 1С. Замените его на символ подчеркивания _ или дефис - на этапе генерации имени файла.

← На главную