1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-11-25 22:12:29 +02:00
Files
OpenIntegrations/XML/CommonModules/OPI_FTP/Ext/Module.bsl
Vitaly the Alpaca (bot) cdef2d02ab Main build (Jenkins)
2025-10-21 21:43:05 +03:00

1144 lines
57 KiB
Plaintext

// OneScript: ./OInt/core/Modules/OPI_FTP.os
// Lib: FTP
// CLI: ftp
// Keywords: ftp, ftps
// MIT License
// Copyright (c) 2023-2025 Anton Tsitavets
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// https://github.com/Bayselonarrend/OpenIntegrations
// BSLLS:Typo-off
// BSLLS:LatinAndCyrillicSymbolInWord-off
// BSLLS:IncorrectLineBreak-off
// BSLLS:NumberOfOptionalParams-off
// BSLLS:UsingServiceTag-off
// BSLLS:LineLength-off
// BSLLS:UsingSynchronousCalls-off
// BSLLS:MagicNumber-off
//@skip-check module-structure-top-region
//@skip-check module-structure-method-in-regions
//@skip-check wrong-string-literal-content
//@skip-check method-too-many-params
#Область ПрограммныйИнтерфейс
#Область ОсновныеМетоды
// Открыть соединение !NOCLI
// Открывает FTP соединение с указанными настройками
//
// Параметры:
// НастройкиFTP - Структура Из КлючИЗначение - Настройки FTP. См. ПолучитьНастройкиСоединения - set
// Прокси - Структура Из КлючИЗначение - Настройки прокси, если необходимо. См. ПолучитьНастройкиПрокси - proxy
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Произвольный - Объект коннектора или соответствие с информацией об ошибке
Функция ОткрытьСоединение(Знач НастройкиFTP, Знач Прокси = Неопределено, Знач Tls = Неопределено) Экспорт
Result_ = "result";
Если ЭтоКоннектор(НастройкиFTP) Тогда
Возврат НастройкиFTP;
КонецЕсли;
Коннектор = OPI_Компоненты.ПолучитьКомпоненту("FTP");
УстановкаНастроек = УстановитьНастройкиFtp(Коннектор, НастройкиFTP);
Если Не OPI_Инструменты.ПолучитьИли(УстановкаНастроек, Result_, Ложь) Тогда
Возврат УстановкаНастроек;
КонецЕсли;
Tls = OPI_Компоненты.УстановитьTls(Коннектор, Tls);
Если Не OPI_Инструменты.ПолучитьИли(Tls, Result_, Ложь) Тогда
Возврат Tls;
КонецЕсли;
УстановитьПрокси = УстановитьНастройкиПрокси(Коннектор, Прокси);
Если Не OPI_Инструменты.ПолучитьИли(УстановитьПрокси, Result_, Ложь) Тогда
Возврат УстановитьПрокси;
КонецЕсли;
Результат = Коннектор.Connect();
Результат = OPI_Инструменты.JSONВСтруктуру(Результат);
Возврат ?(Результат[Result_], Коннектор, Результат);
КонецФункции
// Получить конфигурацию соединения
// Формирует полную структуру настроек соединения, которая может быть использована вместо самого соединения при вызове других функций
//
// Примечание:
// Может быть передана в качестве параметра `Соединение` в других функциях вместо настоящего соединения из функции `ОткрытьСоединение`.^^
// При этом новое соединение будет открыто и закрыто в рамках вызываемой функции
// Не рекомендуется использовать конфигурацию соединения при множественных обращениях к серверу FTP.^^
// Данный функционал предназначен, в первую очередь для CLI версии ОПИ, где хранение соединения между вызовами невозможно
//
// Параметры:
// НастройкиFTP - Структура Из КлючИЗначение - Настройки FTP. См. ПолучитьНастройкиСоединения - set
// Прокси - Структура Из КлючИЗначение - Настройки прокси, если необходимо. См. ПолучитьНастройкиПрокси - proxy
// Tls - Структура Из КлючИЗначение - Настройки TLS, если необходимо. См. ПолучитьНастройкиTls - tls
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек соединения
Функция ПолучитьКонфигурациюСоединения(Знач НастройкиFTP, Знач Прокси = Неопределено, Знач Tls = Неопределено) Экспорт
Коллекция_ = "Коллекция";
СтруктураКонфигурации = Новый Структура;
OPI_Инструменты.ДобавитьПоле("set" , НастройкиFTP, Коллекция_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("proxy", Прокси , Коллекция_, СтруктураКонфигурации);
OPI_Инструменты.ДобавитьПоле("tls" , Tls , Коллекция_, СтруктураКонфигурации);
Возврат СтруктураКонфигурации;
КонецФункции
// Закрыть соединение !NOCLI
// Явно закрывает переданное соединение
//
// Параметры:
// Соединение - Произвольный - Объект компоненты с открытым соединением - conn
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Результат закрытия соединения
Функция ЗакрытьСоединение(Знач Соединение) Экспорт
ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
КонецЕсли;
Результат = Соединение.Close();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
//@skip-check constructor-function-return-section
Возврат Результат;
КонецФункции
// Получить приветственное сообщение
// Получает приветственное сообщение сервера FTP
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьПриветственноеСообщение(Знач Соединение) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
Результат = Соединение.GetWelcomeMsg();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить список расширений протокола
// Получает список расширений протокола FTP, поддерживаемых сервером
//
// Примечание:
// Команда FTP: `FEAT`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокРасширенийПротокола(Знач Соединение) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
Результат = Соединение.GetFeatures();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Пинг
// Проверяет активность соединения и сбрасывает таймаут до его автоматического закрытия
//
// Примечание:
// Команда FTP: `NOOP`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
//
// Возвращаемое значение:
// Булево - Успешность обращения к серверу
Функция Пинг(Знач Соединение) Экспорт
ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
Результат = Соединение.Ping();
КонецЕсли;
ЗакрытьСоединение(Соединение);
Возврат Результат;
КонецФункции
// Выполнить нестандартную команду
// Выполняет специфическую (SITE) команду сервера и возвращает ответ
//
// Примечание:
// Результат может быть возвращен как текст или Base64 довичные данные в структуре `{"BYTES": <B64 строка>}`
// Команда FTP: `SITE`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// ТекстКоманды - Строка - Текст выполняемой команды - cmd
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ВыполнитьНестандартнуюКоманду(Знач Соединение, Знач ТекстКоманды) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстКоманды);
Результат = Соединение.ExecuteCommand(ТекстКоманды);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Выполнить произвольную команду
// Отправляет произвольный текстовый запрос на сервер для обработки
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// ТекстКоманды - Строка - Текст выполняемой команды - cmd
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ВыполнитьПроизвольнуюКоманду(Знач Соединение, Знач ТекстКоманды) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(ТекстКоманды);
Результат = Соединение.ExecuteStandardCommand(ТекстКоманды);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить размер объекта
// Получает размер файла или директории, если она существуют
//
// Примечание:
// Команда FTP: `SIZE`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к объекту - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьРазмерОбъекта(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.GetObjectSize(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Изменить путь
// Изменяет путь объекта на указанный
//
// Примечание:
// Возможность перемещения объекта из одного каталога в другой при помощи изменения пути зависит от настроек сервера
// Команда FTP: `RNFR + RNTO`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Текущий путь к объекту - old
// НовыйПуть - Строка - Новый путь к объекту - new
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ИзменитьПуть(Знач Соединение, Знач Путь, Знач НовыйПуть) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(НовыйПуть);
Результат = Соединение.RenameObject(Путь, НовыйПуть);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Это коннектор !NOCLI
// Проверяет, что значение является объектом внешней компоненты для работы с FTP
//
// Параметры:
// Значение - Произвольный - Значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это коннектор
Функция ЭтоКоннектор(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_FTP.Main";
КонецФункции
// BSLLS:NumberOfParams-off
// Получить настройки соединения
// Формирует структуру настроек подключения FTP
//
// Примечание:
// При `РазрешениеIP = Истина` адрес для подключения, возвращаемый сервером в пассивном режиме после `PASV`, будет заменен на IP^^
// сервера из поля `Хост` в тех случаях, когда используется прокси или сервер вернул `127.0.0.1` (только при указании IP адреса в поле `Хост`)
//
// Параметры:
// Хост - Строка - Адрес сервера - host
// Порт - Число - Порт сервера - port
// Логин - Строка, Неопределено - Имя пользователя авторизации, если необходимо - login
// Пароль - Строка, Неопределено - Пароль пользователя для авторизации, если необходимо - pass
// Пассивный - Булево - Пассивный режим соединения - passive
// ТаймаутЧтения - Число - Таймаут чтения - rtout
// ТаймаутЗаписи - Число - Таймаут записи - wtout
// РазрешениеIP - Булево - Расширенное определение адресов в пассивном режиме - ipresl
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек соединения
Функция ПолучитьНастройкиСоединения(Знач Хост
, Знач Порт = 21
, Знач Логин = Неопределено
, Знач Пароль = Неопределено
, Знач Пассивный = Истина
, Знач ТаймаутЧтения = 120
, Знач ТаймаутЗаписи = 120
, Знач РазрешениеIP = Истина) Экспорт
Число_ = "Число";
СтруктураНастроек = Новый Структура;
OPI_Инструменты.ДобавитьПоле("domain" , Хост , "Строка", СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("port" , Порт , Число_ , СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("passive" , Пассивный , "Булево", СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("read_timeout" , ТаймаутЧтения , Число_ , СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("write_timeout" , ТаймаутЗаписи , Число_ , СтруктураНастроек);
OPI_Инструменты.ДобавитьПоле("advanced_resolve", РазрешениеIP , "Булево", СтруктураНастроек);
Если Не Логин = Неопределено Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(Логин);
СтруктураНастроек.Вставить("login", Логин);
КонецЕсли;
Если Не Пароль = Неопределено Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(Пароль);
СтруктураНастроек.Вставить("password", Пароль);
КонецЕсли;
//@skip-check constructor-function-return-section
Возврат СтруктураНастроек;
КонецФункции
// BSLLS:NumberOfParams-on
// Получить настройки прокси
// Формирует структуру настроек прокси-сервера для соединения
//
// Параметры:
// Адрес - Строка - Адрес прокси - addr
// Порт - Число - Порт прокси - port
// Вид - Строка - Вид прокси: socks5, socks4, http - type
// Логин - Строка, Неопределено - Логин авторизации, если необходимо - login
// Пароль - Строка, Неопределено - Пароль для авторизации, если необходимо - pass
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек прокси
Функция ПолучитьНастройкиПрокси(Знач Адрес
, Знач Порт
, Знач Вид = "socks5"
, Знач Логин = Неопределено
, Знач Пароль = Неопределено) Экспорт
//@skip-check constructor-function-return-section
Возврат OPI_Компоненты.ПолучитьНастройкиПрокси(Адрес, Порт, Вид, Логин, Пароль);
КонецФункции
// Получить настройки TLS
// Формирует настройки для использования TLS при выполнении запросов
//
// Примечание:
// Настройки Tls могут быть установлены только в момент создания соединения: явного, при использовании функции `ОткрытьСоединение`^^
// или неявного, при передаче настроек
//
// Параметры:
// ОтключитьПроверкуСертификатов - Булево - Позволяет работать с некорретными сертификатами, в т.ч. самоподписанными - trust
// ПутьКСертификату - Строка - Путь к корневому PEM файлу сертификата, если его нет в системном хранилище - cert
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура настроек TLS соединения
Функция ПолучитьНастройкиTls(Знач ОтключитьПроверкуСертификатов, Знач ПутьКСертификату = "") Экспорт
Возврат OPI_Компоненты.ПолучитьНастройкиTls(ОтключитьПроверкуСертификатов, ПутьКСертификату);
КонецФункции
#КонецОбласти
#Область РаботаСДиректориями
// Получить список объектов
// Получает информацию о содержимом директории по выбранному пути
//
// Примечание:
// Команда FTP: `LIST`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к директории поиска - path
// Рекурсивно - Булево - Получать информацию об объектах во вложенных директориях - rcv
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьСписокОбъектов(Знач Соединение, Знач Путь = "", Знач Рекурсивно = Ложь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьБулево(Рекурсивно);
Путь = ?(Путь = ".", "", Путь);
Результат = Соединение.ListDirectory(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Если Результат["result"] Тогда
СписокОбъектов = Результат["data"];
ОбработатьСписокОбъектов(СписокОбъектов, Путь, Соединение, Рекурсивно);
Результат = Новый Соответствие;
Результат.Вставить("result", Истина);
Результат.Вставить("data" , СписокОбъектов);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать новую директорию
// Создает директорию по указанному пути
//
// Примечание:
// Команда FTP: `MKD`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к новой директории - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СоздатьНовуюДиректорию(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.MakeDirectory(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Удалить директорию
// Удаляет существующую директорию
//
// Примечание:
// Команда FTP: `RMD`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к удаляемой директории - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьДиректорию(Знач Соединение, Знач Путь) Экспорт
Возврат ОчиститьУдалитьДиректорию(Соединение, Путь, Истина);
КонецФункции
// Очистить директорию
// Очищает выбранную директорию
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к очищаемой директории - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ОчиститьДиректорию(Знач Соединение, Знач Путь) Экспорт
Возврат ОчиститьУдалитьДиректорию(Соединение, Путь, Ложь);
КонецФункции
// Получить текущий каталог
// Получает текущий каталог, от которого вычисляются относительные пути
//
// Примечание:
// Команда FTP: `PWD`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ПолучитьТекущийКаталог(Знач Соединение) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
Результат = Соединение.GetCurrentDirectory();
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Изменить текущий каталог !NOCLI
// Изменяет текущий каталог, от которого вычисляются относительные пути
//
// Примечание:
// Команда FTP: `CWD`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь к новой директории - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ИзменитьТекущийКаталог(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.ChangeCurrentDirectory(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#Область РаботаСФайлами
// Загрузить файл
// Загружает файл с диска или двоичные данные на сервер FTP
//
// Примечание:
// Команда FTP: `STOR`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Файл - Строка, ДвоичныеДанные - Файл на диске или данные файла - file
// Путь - Строка - Путь сохранения файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция ЗагрузитьФайл(Знач Соединение, Знач Файл, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
СоединениеОбработки = ПолучитьСоединениеДляФайловойОперации(Соединение, ЗакрыватьСоединение);
Если Не ЭтоКоннектор(СоединениеОбработки) Тогда
Возврат СоединениеОбработки;
КонецЕсли;
Если ТипЗнч(Файл) = Тип("Строка") Тогда
ФайлНаДиске = Новый Файл(Файл);
ЭтоФайлНаДиске = ФайлНаДиске.Существует();
Иначе
ЭтоФайлНаДиске = Ложь;
КонецЕсли;
Если Не ЭтоФайлНаДиске Тогда
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл);
Если OPI_Компоненты.ТребуетсяПередачаЧерезФайл() Тогда
// BSLLS:MissingTemporaryFileDeletion-off
//@skip-check missing-temporary-file-deletion
ИВФ = ПолучитьИмяВременногоФайла();
// BSLLS:MissingTemporaryFileDeletion-on
Файл.Записать(ИВФ);
Результат = СоединениеОбработки.UploadFile(ИВФ, Путь);
OPI_Инструменты.УдалитьФайлВПопытке(ИВФ, "Не удалось удалить временный файл после загрузки");
Иначе
Результат = СоединениеОбработки.UploadData(Файл, Путь);
КонецЕсли;
Иначе
Результат = СоединениеОбработки.UploadFile(Файл, Путь);
КонецЕсли;
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Удалить файл
// Удаляет файл с сервера
//
// Примечание:
// Команда FTP: `DELE`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция УдалитьФайл(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = Соединение.RemoveFile(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Сохранить файл
// Сохраняет файл с сервера по указанному пути
//
// Примечание:
// Команда FTP: `RETR`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
// ИмяФайла - Строка - Путь для сохранения файла на диске - file
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение - Результат обработки
Функция СохранитьФайл(Знач Соединение, Знач Путь, Знач ИмяФайла) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
OPI_ПреобразованиеТипов.ПолучитьСтроку(ИмяФайла);
OPI_Инструменты.ВернутьУправляющиеПоследовательности(ИмяФайла);
Результат = Соединение.DownloadToFile(Путь, ИмяФайла);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получить данные файла !NOCLI
// Получает файл с сервера как двоичные данные
//
// Примечание:
// Команда FTP: `RETR`
//
// Параметры:
// Соединение - Произвольный - Существующее соединение или конфигурация соединения - conn
// Путь - Строка - Путь файла на сервере - path
//
// Возвращаемое значение:
// Соответствие Из КлючИЗначение, ДвоичныеДанные - Данные файла или информация об ошибке
Функция ПолучитьДанныеФайла(Знач Соединение, Знач Путь) Экспорт
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Если OPI_Компоненты.ТребуетсяПередачаЧерезФайл() Тогда
// BSLLS:MissingTemporaryFileDeletion-off
//@skip-check missing-temporary-file-deletion
ИВФ = ПолучитьИмяВременногоФайла();
// BSLLS:MissingTemporaryFileDeletion-on
Результат = Соединение.DownloadToFile(Путь, ИВФ);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Если Результат["result"] Тогда
Данные = Новый ДвоичныеДанные(ИВФ);
OPI_Инструменты.УдалитьФайлВПопытке(ИВФ, "Не удалось удалить временный файл после загрузки");
Возврат Данные;
КонецЕсли;
Иначе
Данные = Соединение.DownloadToBuffer(Путь);
Если ТипЗнч(Данные) = Тип("Строка") Тогда
Результат = OPI_Инструменты.JsonВСтруктуру(Данные);
Иначе
Возврат Данные;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция УстановитьНастройкиFtp(Знач Коннектор, Знач НастройкиFTP)
ТекстОшибки = "Настройки FTP не являются валидной структурой ключ-значение";
Настройки = НастройкиВJson(НастройкиFTP, ТекстОшибки);
Если ТипЗнч(Настройки) = Тип("Соответствие") Тогда
Возврат Настройки;
КонецЕсли;
Результат = Коннектор.UpdateSettings(Настройки);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Возврат Результат;
КонецФункции
Функция УстановитьНастройкиПрокси(Знач Коннектор, Знач НастройкиПрокси)
Если НастройкиПрокси = Неопределено Тогда
Результат = Новый Соответствие;
Результат.Вставить("result", Истина);
Возврат Результат;
КонецЕсли;
ТекстОшибки = "Настройки прокси не являются валидной структурой ключ-значение";
Настройки = НастройкиВJson(НастройкиПрокси, ТекстОшибки);
Если ТипЗнч(Настройки) = Тип("Соответствие") Тогда
Возврат Настройки;
КонецЕсли;
Результат = Коннектор.UpdateProxy(Настройки);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Возврат Результат;
КонецФункции
Функция НастройкиВJson(Знач Коллекция, Знач ТекстОшибки)
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Коллекция);
Попытка
Результат = OPI_Инструменты.JSONСтрокой(Коллекция);
Исключение
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , "Настройки FTP должны содержать только сериализуемые значения");
КонецПопытки;
Возврат Результат;
КонецФункции
Функция ОткрытьСоединениеПоКонфигурации(Знач СтруктураКонфигурации)
Если ЭтоКоннектор(СтруктураКонфигурации) Тогда
Возврат СтруктураКонфигурации;
КонецЕсли;
ШаблонОшибки = "Передана некорректная конфигурация соединения: %1";
Попытка
OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(СтруктураКонфигурации);
Исключение
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, ОписаниеОшибки()));
Возврат Результат;
КонецПопытки;
Если Не OPI_Инструменты.ПолеКоллекцииСуществует(СтруктураКонфигурации, "set") Тогда
Результат = Новый Соответствие;
Результат.Вставить("result", Ложь);
Результат.Вставить("error" , СтрШаблон(ШаблонОшибки, "отсутствуют основные параметры соединения"));
Возврат Результат;
КонецЕсли;
НастройкиFTP = СтруктураКонфигурации["set"];
Прокси = OPI_Инструменты.ПолучитьИли(СтруктураКонфигурации, "proxy", Неопределено);
Tls = OPI_Инструменты.ПолучитьИли(СтруктураКонфигурации, "tls", Неопределено);
Возврат ОткрытьСоединение(НастройкиFTP, Прокси, Tls);
КонецФункции
Функция ПроверитьСоздатьСоединение(Соединение)
Если ЭтоКоннектор(Соединение) Тогда
Проверка = Соединение.Ping();
Если Не Проверка Тогда
Соединение = ПолучитьКопиюСоединения(Соединение);
КонецЕсли;
ЗакрыватьСоединение = Ложь;
Иначе
ЗакрыватьСоединение = Истина;
Соединение = ОткрытьСоединениеПоКонфигурации(Соединение);
КонецЕсли;
Возврат ЗакрыватьСоединение;
КонецФункции
Функция ОчиститьУдалитьДиректорию(Знач Соединение, Знач Путь, Знач УдалятьТекущую)
ЗакрыватьСоединение = ПроверитьСоздатьСоединение(Соединение);
Если Не ЭтоКоннектор(Соединение) Тогда
Возврат Соединение;
Иначе
OPI_ПреобразованиеТипов.ПолучитьСтроку(Путь);
Результат = УдалитьДиректориюРекурсивно(Соединение, Путь, УдалятьТекущую);
КонецЕсли;
Если ЗакрыватьСоединение Тогда
Результат.Вставить("close_connection", ЗакрытьСоединение(Соединение));
КонецЕсли;
Возврат Результат;
КонецФункции
Функция УдалитьДиректориюРекурсивно(Знач Соединение, Знач Путь, Знач УдалятьТекущую = Истина, МассивУдаленных = Неопределено)
Если МассивУдаленных = Неопределено Тогда
МассивУдаленных = Новый Массив;
Основной = Истина;
Иначе
Основной = Ложь;
КонецЕсли;
ВложенныеОбъекты = ПолучитьСписокОбъектов(Соединение, Путь, Истина);
Если ВложенныеОбъекты["result"] Тогда
Для Каждого Объект Из ВложенныеОбъекты["data"] Цикл
ПутьОбъекта = Объект["path"];
Если Объект["is_directory"] Тогда
Удаление = УдалитьДиректориюРекурсивно(Соединение, ПутьОбъекта, УдалятьТекущую, МассивУдаленных);
Иначе
Удаление = УдалитьФайл(Соединение, ПутьОбъекта);
КонецЕсли;
Удаление.Вставить("path", ПутьОбъекта);
МассивУдаленных.Добавить(Удаление);
КонецЦикла;
Иначе
Возврат ВложенныеОбъекты;
КонецЕсли;
Если Не Основной Или УдалятьТекущую Тогда
Результат = Соединение.RemoveDirectory(Путь);
Результат = OPI_Инструменты.JsonВСтруктуру(Результат);
Иначе
Результат = Новый Соответствие;
Результат.Вставить("result", Истина);
КонецЕсли;
Если Основной Тогда
Результат.Вставить("deleted_objects", МассивУдаленных);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолучитьСоединениеДляФайловойОперации(Знач Соединение, Знач ЗакрыватьСоединение)
Если ЗакрыватьСоединение Тогда
Возврат Соединение;
КонецЕсли;
ЭтоTls = Соединение.IsTls();
Если ЭтоTls Тогда
// Избегание не всегда корректно отрабатывающего TLS Session reuse для нескольких data stream
СоединениеОбработки = ПолучитьКопиюСоединения(Соединение);
Иначе
СоединениеОбработки = Соединение;
КонецЕсли;
Возврат СоединениеОбработки;
КонецФункции
Функция ПолучитьКопиюСоединения(Знач Соединение)
Конфигурация = Соединение.GetConfiguration();
Конфигурация = OPI_Инструменты.JSONВСтруктуру(Конфигурация);
Если Не Конфигурация["result"] Тогда
Возврат Конфигурация;
КонецЕсли;
Конфигурация = Конфигурация["data"];
НастройкиFTP = Конфигурация["ftp_settings"];
Прокси = Конфигурация["proxy_settings"];
TLS = Конфигурация["tls_settings"];
Возврат ОткрытьСоединение(НастройкиFTP, Прокси, TLS);
КонецФункции
Процедура ОбработатьСписокОбъектов(СписокОбъектов, Знач Путь, Знач Соединение, Знач Рекурсивно)
Для Каждого Объект Из СписокОбъектов Цикл
ИмяОбъекта = Объект["name"];
Если ЗначениеЗаполнено(Путь) Тогда
ПутьОбъекта = СтрШаблон("%1/%2", Путь, ИмяОбъекта);
Иначе
ПутьОбъекта = ИмяОбъекта;
КонецЕсли;
Объект.Вставить("path", ПутьОбъекта);
Если Рекурсивно Тогда
Если Объект["is_directory"] Тогда
РезультатПодкаталога = ПолучитьСписокОбъектов(Соединение, ПутьОбъекта, Истина);
Если Не РезультатПодкаталога["result"] Тогда
Подкаталоги = РезультатПодкаталога;
Иначе
Подкаталоги = РезультатПодкаталога["data"];
КонецЕсли;
Объект.Вставить("objects", Подкаталоги);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
#КонецОбласти