При организации автоматического обмена данными между базами «1С:Предприятие» и внешними системами разработчики часто сталкиваются с неприятной ситуацией: отлаженный механизм выгрузки файлов на FTP-сервер внезапно начинает сбоить. Файлы отправляются, но на сервере их имена превращаются в нечитаемый набор символов (так называемые «кракозябры» вроде Запчасти), либо сессия обрывается с ошибкой. Особенно остро эта проблема проявляется, когда в именах файлов используются русские буквы (кириллица) или специфические символы, такие как @.
В этой статье мы подробно разберем, почему встроенный механизм FTPСоединение в 1С может искажать кодировку имен файлов, как правильно настроить FTP-сервер для бесконфликтной работы и какие программные обходные пути существуют на стороне платформы 1С.
Для того чтобы понять, как исправить ошибку, проанализируем физику взаимодействия клиента 1С и удаленного FTP-сервера. Проблема кроется в несовпадении стандартов кодирования символов в различных операционных системах:
FTPСоединение под управлением ОС Windows, платформа делегирует работу с сетью системным библиотекам (в частности, WinINet). Эти библиотеки по умолчанию могут транслировать имена файлов в локальную однобайтную кодировку операционной системы — для русскоязычной Windows это Windows-1251 (CP1251).OPTS UTF8 ON. Встроенный клиент 1С в некоторых версиях платформы выполняет это согласование некорректно либо не выполняет вовсе, из-за чего сервер продолжает ожидать данные в локальной кодировке.Ситуация усугубляется, если обмен происходит между разными версиями платформ 1С или операционными системами (например, сервер 1С работает на Linux, а клиенты — на Windows), что сразу приводит к рассинхронизации кодировок.
Если у вас или у ваших системных администраторов есть доступ к управлению 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С сервер выполнит обратную конвертацию, и платформа без ошибок прочитает имена файлов.
Если 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-файла обмена.
Когда стандартный объект платформы 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.
Помимо кодировки, при работе с объектом FTPФайл программисты часто сталкиваются со странным поведением: имя файла обрезается, если в нем присутствует символ «собаки» (@).
Выясним причину этого бага. Внутренний синтаксический анализатор (парсер) путей в платформе 1С написан таким образом, что он пытается разбирать переданные строки как URL-адреса. В спецификации URL символ @ является разделителем авторизационных данных пользователя и адреса хоста (например: ftp://логин:пароль@сервер).
Когда парсер 1С натыкается на символ @ внутри имени файла (например, otchet_@_01.xml), он ошибочно считает все, что находится до этого символа, логином и паролем, а остальную часть строки — адресом сервера. В результате имя файла искажается, обрезается, а система выдает ошибку о невозможности найти файл.
Решение проблемы с "@": Единственным надежным решением является полное исключение символа @ из путей и названий файлов при работе через встроенные механизмы 1С. Замените его на символ подчеркивания _ или дефис - на этапе генерации имени файла.