В практике интеграции 1С с внешними системами мы часто сталкиваемся с задачей передачи файлов, например, когда требуется реализовать сохранение CF на FTP по расписанию. Стандартный протокол FTP остается одним из самых популярных способов обмена данными. Однако, когда платформа 1С (чаще всего работающая в среде Windows) пытается передать файл с русским именем на FTP-сервер под управлением Linux (например, Ubuntu или защищенная инфраструктура на базе Astra Linux), вместо читаемого названия мы получаем набор непонятных символов («кракозябры»).
Давайте разберемся, почему так происходит, почему стандартные методы не помогают, и рассмотрим несколько надежных способов решения этой задачи.
Прежде чем переходить к коду, давайте проанализируем техническую сторону процесса. Проблема кроется не в содержимом файла, а в том, как передается его имя в управляющем соединении FTP.
FTPСоединение в платформе 1С при отправке команд (например, STOR для записи файла) использует кодировку операционной системы, в которой запущен клиент или сервер 1С. Для русскоязычной Windows это обычно CP1251 (ANSI).Важно понимать различие, которое часто упускают новички: кодировка содержимого файла (например, текста внутри .txt) и кодировка его имени — это две разные вещи.
Рассмотрим популярное заблуждение:
ТекстовыйДок.Записать(ИмяФайла, КодировкаТекста.UTF8);
Этот код задает кодировку внутри файла. Он никак не влияет на то, как имя этого файла будет передано по сети.
Если бизнес-процесс позволяет, самым надежным и простым решением является полный отказ от кириллицы в именах файлов при передаче. Это гарантирует, что файл будет корректно прочитан любой системой, будь то Windows, Linux или MacOS, так как латиница (ASCII) везде одинакова.
Давайте реализуем функцию транслитерации и применим её перед отправкой.
Функция ТранслитерироватьСтроку(Значение) Экспорт
Результат = "";
СоответствиеСимволов = Новый Соответствие;
СоответствиеСимволов.Вставить("а", "a"); СоответствиеСимволов.Вставить("А", "A");
СоответствиеСимволов.Вставить("б", "b"); СоответствиеСимволов.Вставить("Б", "B");
СоответствиеСимволов.Вставить("в", "v"); СоответствиеСимволов.Вставить("В", "V");
// ... здесь необходимо заполнить весь алфавит ...
СоответствиеСимволов.Вставить("я", "ya"); СоответствиеСимволов.Вставить("Я", "YA");
СоответствиеСимволов.Вставить(" ", "_"); // Заменяем пробелы на подчеркивания для надежности
Для Индекс = 1 По СтрДлина(Значение) Цикл
ТекСимвол = Сред(Значение, Индекс, 1);
Замена = СоответствиеСимволов.Получить(ТекСимвол);
Если Замена <> Неопределено Тогда
Результат = Результат + Замена;
Иначе
// Оставляем цифры и латиницу как есть, остальные символы можно удалять или заменять
Если (ТекСимвол >= "0" И ТекСимвол <= "9")
ИЛИ (ТекСимвол >= "A" И ТекСимвол <= "Z")
ИЛИ (ТекСимвол >= "a" И ТекСимвол <= "z")
ИЛИ ТекСимвол = "." Тогда
Результат = Результат + ТекСимвол;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Теперь применим это при отправке файла:
// Подготовка имен
ИмяИсходногоФайла = "C:\Temp\Договор №123.pdf";
ИмяФайлаНаСервере = "contract_123.pdf"; // Или результат функции ТранслитерироватьСтроку
Попытка
Соединение = Новый FTPСоединение("ftp.server.com", 21, "user", "password");
Соединение.Записать(ИмяИсходногоФайла, "/upload/" + ИмяФайлаНаСервере);
Исключение
Сообщить("Ошибка выгрузки: " + ОписаниеОшибки());
КонецПопытки;
В этом случае мы сохраняем исходное русское наименование где-то в базе данных (например, в регистре сведений, связывающем ID файла и его оригинальное имя), а на FTP храним техническое имя на латинице.
Если отказ от кириллицы невозможен (например, файлы забирает сторонняя система, ожидающая именно русские имена), нам придется отказаться от штатного FTPСоединение. В качестве альтернативы можно рассмотреть использование SFTP для 1С через внешние сервисы или компоненты. Этот объект 1С, к сожалению, плохо умеет договариваться с сервером о кодировке UTF-8 (команда OPTS UTF8 ON согласно RFC 2640).
Вместо этого мы можем использовать мощный инструмент WinSCP, который поддерживает автоматизацию через COM-объект. Это решение работает только если 1С запущена на Windows.
Порядок действий:
Разберем пример кода для отправки файла с принудительным указанием UTF-8:
Функция ОтправитьФайлЧерезWinSCP(ПутьКФайлу, ИмяНаFTP, Хост, Логин, Пароль)
// Создаем объект опций сессии
Попытка
SessionOptions = Новый COMОбъект("WinSCP.SessionOptions");
Исключение
Сообщить("Не удалось создать объект WinSCP. Проверьте установку.");
Возврат Ложь;
КонецПопытки;
// Настройки подключения
SessionOptions.Protocol = 0; // 0 = Sftp, 1 = Scp, 2 = Ftp
SessionOptions.HostName = Хост;
SessionOptions.UserName = Логин;
SessionOptions.Password = Пароль;
// ВАЖНО: Включаем UTF-8 для имен файлов
// Значение 1 соответствует "On" (Включено)
// Это заставит клиент отправлять имена в UTF-8
SessionOptions.Utf8 = 1;
Попытка
// Создаем сессию и подключаемся
Session = Новый COMОбъект("WinSCP.Session");
Session.Open(SessionOptions);
// Опции передачи
TransferOptions = Новый COMОбъект("WinSCP.TransferOptions");
TransferOptions.TransferMode = 0; // 0 = Binary, 1 = Ascii
// Выполняем передачу
// Обратите внимание: WinSCP работает с полными путями
TransferResult = Session.PutFiles(ПутьКФайлу, "/" + ИмяНаFTP, Ложь, TransferOptions);
// Проверяем результат
TransferResult.Check();
Сообщить("Файл успешно отправлен: " + ИмяНаFTP);
// Закрываем сессию
Session.Dispose();
Возврат Истина;
Исключение
Сообщить("Ошибка WinSCP: " + ОписаниеОшибки());
Если Session <> Неопределено Тогда
Session.Dispose();
КонецЕсли;
Возврат Ложь;
КонецПопытки;
КонецФункции
Использование WinSCP решает проблему на уровне протокола, так как этот клиент корректно обрабатывает стандарты кодирования, в отличие от устаревшей реализации в платформе 1С.
Если вы не хотите регистрировать COM-объекты, можно воспользоваться утилитой командной строки cURL. Она доступна в современных версиях Windows 10/11 и Server 2019+ по умолчанию, либо её можно скачать отдельно. cURL отлично справляется с кодировками.
Посмотрим, как запустить cURL из 1С:
Процедура ОтправитьФайлCurl(ПутьЛокальный, ИмяНаСервере, Хост, Юзер, Пароль)
// Формируем команду. Важно использовать экранирование кавычек
// curl -T "C:\local\file.pdf" ftp://user:pass@host/remote_file.pdf
// Внимание: передача пароля в командной строке небезопасна, если систему мониторят другие пользователи
СтрокаКоманды = "curl -T """ + ПутьЛокальный + """ " +
"ftp://" + Юзер + ":" + Пароль + "@" + Хост + "/" + ИмяНаСервере;
ЗапуститьПриложение(СтрокаКоманды, , Истина); // Истина = ждать завершения
КонецПроцедуры
Однако, здесь есть нюанс: сама командная строка Windows (cmd.exe) должна корректно воспринимать кириллицу при передаче параметров. Для этого может потребоваться предварительное сохранение команды в .bat файл в кодировке CP866 или использование chcp 65001.
В обсуждении часто советуют настроить FTP-сервер. Давайте проанализируем, почему это редко помогает в случае с 1С.
Большинство Linux-серверов используют vsftpd или ProFTPD.
utf8_filesystem=YES, он будет ожидать строго UTF-8. Когда 1С присылает CP1251, сервер видит недопустимую последовательность байтов и либо разрывает соединение, либо создает «битый» файл. Он не умеет конвертировать кодировку «на лету».mod_lang. Если администратор сервера пропишет настройку UseEncoding UTF-8 CP1251, сервер будет знать: «Клиент присылает CP1251, я должен переделать это в UTF-8». Это решит проблему без изменений кода 1С. Однако не всегда у программиста 1С есть доступ к настройкам сервера заказчика.Чтобы сэкономить ваше время, перечислим методы, которые предлагались, но технически не решают проблему:
XMLСтрока(ИмяФайла) — это преобразует строку в XML-безопасный формат, но не меняет кодировку передачи имени файла на уровне сокета.ПолучитьБуферДвоичныхДанныхИзСтроки перед передачей в метод Записать. Метод Записать ожидает строку (String), и платформа снова перекодирует её в ANSI перед отправкой, что приведет к двойному искажению.Проблема кириллицы на FTP при работе из 1С — это классический конфликт стандартов старых Windows-приложений и современного мира Linux/Web. Подведем итоги:
FTPСоединение перекодированием строк вручную, это не сработает из-за внутренней реализации платформы.