суббота, 24 августа 2019 г.

Обмен файлами с SFTP-сервером из 1С через WinSCP

Для начала необходимо:
 1) установить программу WinSCP или использовать ее версию portable;
 2) скачать COM-библиотеку с сайта WinSCP и зарегистрировать:
%WINDIR%\Microsoft.NET\Framework\версия\RegAsm.exe WinSCP.dll /codebase /tlb
64-разрядная версия не сработала, поэтому пришлось использовать 32-разрядную.

Ссылка на инструкцию по установке: https://winscp.net/eng/docs/library_install

Ссылка на текущий код 1С: https://yadi.sk/d/S-2yDaTxKKytpg

Код:


Процедура СкачатьФайлыИзSFTP(ВхПар) Экспорт
Каталог1С = КаталогСоСлешем(ВхПар.Каталог1С);
КаталогSFTP = КаталогСоСлешем(ВхПар.КаталогSFTP);

// Подключяемся к SFTP
РезПодкл = Подключение_к_SFTP(ВхПар);
Если РезПодкл.Ошибка Тогда
ЗафиксироватьОшибку(РезПодкл, ВхПар, Дата);
Возврат;
КонецЕсли;

// Поиск файлов на FTP.   
Попытка
// Скачиваем файлы.
       РезЗагр = РезПодкл.SFTP_Соединение.GetFiles(КаталогSFTP + "*", Каталог1С);

// Проверка ошибок.
        РезЗагр.Check();

// Удаляем скачанные файлы.
Для каждого ТекФайл Из РезЗагр.Transfers Цикл
Попытка
            РезПодкл.SFTP_Соединение.RemoveFiles(ТекФайл.FileName);
Исключение
СтруктураВозврата.Ошибка = Истина;
ТекстОш = ОписаниеОшибки();
СтруктураВозврата.ТекстСообщения = ?(ПустаяСтрока(СтруктураВозврата.ТекстСообщения, ТекстОш, СтруктураВозврата.ТекстСообщения + Символы.ПС + ТекстОш);
КонецПопытки;
КонецЦикла;
ЗакрытьПодключение_к_SFTP(РезПодкл.SFTP_Соединение);
Исключение
СтруктураВозврата.Ошибка = Истина;
ТекстОш = ОписаниеОшибки();
СтруктураВозврата.ТекстСообщения = ?(ПустаяСтрока(СтруктураВозврата.ТекстСообщения, ТекстОш, СтруктураВозврата.ТекстСообщения + Символы.ПС + ТекстОш);
ЗафиксироватьОшибку(СтруктураВозврата, ВхПар, Дата);
Возврат;
КонецПопытки;
КонецПроцедуры

Процедура ВыгрузитьФайлыНаSFTP(ВхПар) Экспорт
КаталогSFTP = КаталогСоСлешем(ВхПар.КаталогSFTP);

// Подключяемся к SFTP.
РезПодкл = Подключение_к_SFTP(ВхПар);
Если РезПодкл.Ошибка Тогда
ЗафиксироватьОшибку(РезПодкл, ВхПар, Дата);
Возврат;
КонецЕсли;
     
Для Каждого ПолноеИмяФайла Из ВхПар.МассивИменФайлов Цикл
Выгружен = Ложь;
ТекФайл = Новый Файл(ПолноеИмяФайла);
ПолноеИмяФайлаНаSFTP = КаталогSFTP + ТекФайл.Имя;
Попытка
ТекстОшВыгр = "";
РезВыгр = РезПодкл.SFTP_Соединение.PutFiles(ПолноеИмяФайла, ПолноеИмяФайлаНаSFTP);

// Проверка ошибок.
        РезВыгр.Check();

// Обрабатываем результат выгрузки.
        Для каждого ВыгрФайл Из РезВыгр.Transfers Цикл
            Выгружен = Истина;
КонецЦикла;

Исключение
ТекстОшВыгр = ОписаниеОшибки();
КонецПопытки;

Если НЕ Выгружен Тогда
ТекстОш = "Не удалось отправить файл '" + ПолноеИмяФайла + "'. Подробнее: " + ОписаниеОшибки();
тСообщ = ?(ПустаяСтрока(СтруктураВозврата.ТекстСообщения), ТекстОш, СтруктураВозврата.ТекстСообщения + Символы.ПС + ТекстОш);
СтруктураВозврата.ТекстСообщения = тСообщ;
СтруктураВозврата.Ошибка = Истина;
КонецЕсли;
КонецЦикла;

ЗакрытьПодключение_к_SFTP(РезПодкл.SFTP_Соединение);
Исключение
СтруктураВозврата.Ошибка = Истина;
ТекстОш = ОписаниеОшибки();
СтруктураВозврата.ТекстСообщения = ?(ПустаяСтрока(СтруктураВозврата.ТекстСообщения, ТекстОш, СтруктураВозврата.ТекстСообщения + Символы.ПС + ТекстОш);
КонецПопытки;
Если СтруктураВозврата.Ошибка Тогда
ЗафиксироватьОшибку(СтруктураВозврата, ВхПар, Дата);
КонецЕсли;
КонецПроцедуры

Функция Подключение_к_SFTP(ВхПар) Экспорт
СтруктураВозврата = НоваяСтруктураВозврата();
СтруктураВозврата.Вставить("SFTP_Соединение", Неопределено);

СтрокаСоединенияИБ = СтрокаСоединенияИнформационнойБазы();
Если СОКРЛП(ВРЕГ(СтрокаСоединенияИБ)) <> СОКРЛП(ВРЕГ(ВхПар.СтрокаСоединенияСБазой1С)) Тогда
СтруктураВозврата.Ошибка = Истина;
СтруктураВозврата.ТекстСообщения = "Это не рабочая база - адрес рабочей базы отличается от адреса текущей базы.";
Возврат СтруктураВозврата;
КонецЕсли;

// Подключаемся к SFTP через создание WinSCP-сессии.
Попытка
// Задаем параметры подключения.
        ПарWinSCP = Новый COMОбъект("WinSCP.SessionOptions");
        ПарWinSCP.HostName = ВхПар.СерверSFTP;
ПарWinSCP.PortNumber = ВхПар.ПортSFTP;
        ПарWinSCP.UserName = ВхПар.ЛогинSFTP;
        ПарWinSCP.Password = ВхПар.ПарольSFTP;
        // ПарWinSCP.SshHostKeyFingerprint = "ssh-rsa 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx";
// ПарWinSCP.SshHostKeyFingerprint = "ssh-ed97478 256 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx";
ПарWinSCP.SshHostKeyFingerprint = ВхПар.КлючSFTP;
ПарWinSCP.GiveUpSecurityAndAcceptAnySshHostKey = ВхПар.GiveUpSecurityAndAcceptAnySshHostKey;
         
        СессияWinSCP = Новый COMОбъект("WinSCP.Session"); // Создаем объект Session.
     
        СессияWinSCP.ExecutablePath = ВхПар.ПолноеИмяФайлаWinSCP;
     
        // Подключаемся
        СессияWinSCP.Open(ПарWinSCP);

СтруктураВозврата.SFTP_Соединение = СессияWinSCP;
Исключение
ТекстСообщения = ОписаниеОшибки();
СтруктураВозврата.ТекстСообщения = ТекстСообщения;
СтруктураВозврата.Ошибка = Истина;
Возврат СтруктураВозврата;
КонецПопытки;
Возврат СтруктураВозврата;
КонецФункции

Процедура ЗакрытьПодключение_к_SFTP(SFTP_Соединение) Экспорт
Если SFTP_Соединение = Неопределено Тогда Возврат; КонецЕсли;
Попытка
    SFTP_Соединение.Dispose();
Исключение
// Ошибка не критична. Возможно, уже соединение было удалено или разорвано ранее.
ТекстОш = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Закрытие SFTP-подключения", УровеньЖурналаРегистрации.Ошибка, "", ТекстОш, ТекстОш);
КонецПопытки;
КонецПроцедуры

Функция НоваяСтруктураВозврата() Экспорт
СтруктураВозврата = Новый Структура;
СтруктураВозврата.Вставить("Ошибка", Ложь);
СтруктураВозврата.Вставить("ТекстСообщения", "");
Возврат СтруктураВозврата;
КонецФункции

Функция КаталогСоСлешем(Каталог)
Каталог = ?(Прав(Каталог, 1) = "\", Каталог, Каталог + "\");
Возврат Каталог;
КонецФункции

Процедура ЗафиксироватьОшибку(Результат, ВхПар, Дата) Экспорт
Сообщить(Результат.ТекстСообщения);
ЗаписьЖурналаРегистрации(ВхПар.ТемаПисьма, УровеньЖурналаРегистрации.Ошибка, ВхПар.Метадан, Результат.ТекстСообщения, Результат.ТекстСообщения);
ОтправитьСообщениеНаПочту(ВхПар.ТемаПисьма, ВхПар.НеобходимыйТекстДляИТ, ВхПар.ТЗАдресаЭлектроннойПочты, Дата);
КонецПроцедуры

Комментариев нет:

Отправить комментарий