При обновлении платформы «1С:Предприятие» разработчики нередко сталкиваются с ситуацией, когда ранее работавший программный код выгрузки файлов на FTP-сервер начинает аварийно завершаться. Рассмотрим типичный сценарий: после перехода на релизы ветки 8.3.9 при инициализации объекта FTPСоединение возникает ошибка «FTP: The server failed to connect to data port», а после попытки скорректировать конструктор появляется сообщение «Upload failed (at start/before it took off)». Разберем по шагам, почему это происходит и как правильно настроить передачу данных.
Начиная с версии платформы 8.3.9, разработчики платформы существенно переработали механизмы работы с интернет-протоколами, включая поддержку защищенных протоколов передачи (FTPS). В конструктор объекта FTPСоединение были добавлены параметры управления защищенным соединением. В некоторых случаях платформа по умолчанию пытается согласовать защищенное соединение или некорректно обрабатывает параметры по умолчанию, если сервер ожидает исключительно незащищенный протокол FTP на стандартном порту 21.
Для исправления первой ошибки («The server failed to connect to data port») необходимо явно передать признак отключения SSL в конструктор соединения с помощью системного перечисления УровеньИспользованияЗащищенногоСоединенияFTP.НеИспользовать.
Посмотрим на пример кода инициализации соединения с явным отключением SSL:
Попытка
// Передаем параметры: Адрес, Порт, Пользователь, Пароль, Прокси, ПассивныйРежим, Таймаут, ЗащищенноеСоединение, УровеньИспользованияЗащищенногоСоединенияFTP
FTPСоединение = Новый FTPСоединение(
АдресFTP,
21,
ИмяПользователя,
Пароль,
,
Истина,
,
,
УровеньИспользованияЗащищенногоСоединенияFTP.НеИспользовать
);
FTPСоединение.Записать(ИмяФайла, СокрЛП(НомерДок) + ".xml");
УдалитьФайлы(ИмяФайла);
Сообщить("Файл удачно отправлен на FTP");
Исключение
Сообщить("Не удалось установить FTP соединение: " + ОписаниеОшибки());
КонецПопытки;
Выясним причину второй ошибки, возникающей непосредственно при вызове метода Записать(). Платформа 1С для работы с сетью использует встроенную библиотеку cURL. Сообщение «Upload failed (at start/before it took off)» соответствует внутренней ошибке cURL 25 и означает, что FTP-сервер отклонил команду начала загрузки файла (команду STOR).
Чаще всего это происходит по следующим причинам:
УстановитьТекущийКаталог() или путь указан относительно корня без ведущего слэша, запись может инициироваться в каталог, закрытый для записи.Истина) пытается отправить команду EPSV. Некоторые межсетевые экраны, маршрутизаторы с технологией FTP ALG или устаревшие FTP-серверы некорректно обрабатывают этот запрос за NAT, в результате чего канал передачи данных блокируется еще до старта отправки.Проанализируем ситуацию с правами на перезапись. Чтобы избежать отклонения команды сервером, перед отправкой файла рекомендуется проверить его наличие на сервере и выполнить удаление старой версии. Также следует явно указывать структуру пути:
Попытка
FTPСоединение = Новый FTPСоединение(
АдресFTP,
21,
ИмяПользователя,
Пароль,
,
Истина,
,
,
УровеньИспользованияЗащищенногоСоединенияFTP.НеИспользовать
);
ИмяЦелевогоФайла = СокрЛП(НомерДок) + ".xml";
// Проверяем наличие файла на сервере перед записью
НайденныеФайлы = FTPСоединение.НайтиФайлы("", ИмяЦелевогоФайла);
Если НайденныеФайлы.Количество() > 0 Тогда
FTPСоединение.Удалить(ИмяЦелевогоФайла);
КонецЕсли;
// Выполняем запись
FTPСоединение.Записать(ИмяФайла, ИмяЦелевогоФайла);
УдалитьФайлы(ИмяФайла);
Сообщить("Файл успешно загружен на FTP");
Исключение
Сообщить("Ошибка при работе с FTP: " + ОписаниеОшибки());
КонецПопытки;
Если сетевой экран блокирует пул динамических портов передачи данных, рассмотрим изменение режима работы FTP. Шестой параметр конструктора FTPСоединение отвечает за пассивный режим:
Истина — соединение работает в пассивном режиме (PASV/EPSV). Клиент сам подключается к порту данных, который сообщает сервер.Ложь — включается активный режим (PORT). Сервер сам открывает обратное соединение на порт клиента. Этот вариант подходит, если клиентский компьютер не находится за строгим NAT или на шлюзе настроен проброс портов.Разберем пример инициализации в активном режиме, если пассивный режим блокируется сетевым оборудованием:
FTPСоединение = Новый FTPСоединение(
АдресFTP,
21,
ИмяПользователя,
Пароль,
,
Ложь, // Отключаем пассивный режим
,
,
УровеньИспользованияЗащищенногоСоединенияFTP.НеИспользовать
);
В платформе 1С разработчик не имеет возможности тонко управлять протоколом cURL, например, принудительно отключить команду EPSV без отключения пассивного режима вообще. Если сетевая инфраструктура сервера или маршрутизатора искажает ответы пассивного режима, надежной альтернативой становится вызов консольной утилиты cURL с флагом --no-epsv через процедуру ЗапуститьПриложение().
Рассмотрим пример выполнения команды через внешнюю утилиту:
ИмяЦелевогоФайла = СокрЛП(НомерДок) + ".xml";
СтрокаКоманды = "curl.exe -T """ + ИмяФайла + """ ftp://" + АдресFTP + "/" + ИмяЦелевогоФайла
+ " --user " + ИмяПользователя + ":" + Пароль + " --no-epsv";
КодВозврата = 0;
ЗапуститьПриложение(СтрокаКоманды, , Истина, КодВозврата);
Если КодВозврата = 0 Тогда
УдалитьФайлы(ИмяФайла);
Сообщить("Файл успешно выгружен с помощью внешней утилиты");
Иначе
Сообщить("Ошибка выгрузки файла. Код ошибки cURL: " + Строка(КодВозврата));
КонецЕсли;
При возникновении проблем с передачей файлов всегда анализируйте логи FTP-сервера, так как 1С маскирует реальные коды ошибок (например, 550 Access Denied или 425 Can't open data connection) за общими сообщениями об ошибках библиотеки передачи данных.