Пример загрузки/выгрузки файлов на SFTP сервер из 1С

Опубликовал Ramz # (ram3) в раздел Программирование - Внешние компоненты

К сожалению 1С пока не позволяет своими средствами обмениваться файлами с SFTP сервером.
Столкнувшись с этой проблемой, оптимальным для себя выбрал вариант с использованием бесплатного SFTP клиента:WinSCP.
Я не нашел в сети примеров работы 1С с этой утилитой через COM-соединение, поэтому выкладываю свой. Возможно кому-то будет полезен.

Первом делом необходимо скачать установочный пакет (можно так же использовать portable-версию) и COM-библиотеку с сайта WinSCP и зарегистрировать ее:

%WINDIR%\Microsoft.NET\Framework\версия\RegAsm.exe WinSCP.dll /codebase /tlb

Подробнее об установке здесь

Теперь можно работать с ней из 1С: 

//СОЕДИНЕНИЕ
	Попытка
		
		//Задаем параметры подключения
		sessionOptions = Новый COMОбъект("WinSCP.SessionOptions"); //Создаем объект SessionOptions
		sessionOptions.HostName = "example.com";
		sessionOptions.UserName = "user";
		sessionOptions.Password = "mypassword";
		sessionOptions.SshHostKeyFingerprint = "ssh-rsa 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx";
		
		
		session = Новый COMОбъект("WinSCP.Session"); //Создаем объект Session
		
		//параметр необходимо использовать если пути регистрации DLL и исполняемого файла различны
		session.ExecutablePath = "C:\Program Files (x86)\WinSCP\winscp.exe";
		
		// Подключаемся
		session.Open(sessionOptions);
	Исключение
		Сообщить(ОписаниеОшибки());
		Возврат;
	КонецПопытки;
	
	//ВЫГРУЗКА
	Попытка
		ПутьВыгрузки = Объект.КаталогВыгрузки+"*";
		ПутьЗагрузкиНаФТП = Объект.КаталогЗагрузкиНаФТПСервере;
		
		//Выгружаем файлы
		transferResult = session.PutFiles(ПутьВыгрузки, ПутьЗагрузкиНаФТП);
		
		//Проверяем результат на возможные ошибки
		transferResult.Check();
		
		//Обрабатываем результат выгрузки
		Для каждого ВыгруженныйФайл Из transferResult.Transfers Цикл
			Сообщить("Выгружен файл: "+ВыгруженныйФайл.FileName);
			ПереместитьФайл(ВыгруженныйФайл.FileName, ХранилищеВыгруженныхФайлов);
		КонецЦикла;	
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;
	
	//ЗАГРУЗКА
	Попытка
		ПутьЗагрузки = Объект.КаталогЗагрузки+"\*";
		ПутьВыгрузкиНаФТП = Объект.КаталогВыгрузкиНаФТПСервере;
		
		//Загружаем файлы с удаленного сервера
		transferResult = session.GetFiles(ПутьВыгрузкиНаФТП, ПутьЗагрузки);
		
		//Проверяем возможные ошибки
		transferResult.Check();
		
		//Обрабатываем результат
		Для каждого ЗагруженныйФайл Из transferResult.Transfers Цикл
			Сообщить("Загружен файл: "+ЗагруженныйФайл.FileName);
			session.RemoveFiles(ЗагруженныйФайл.FileName); //Удаляем уже скаченные файлы
		КонецЦикла;
		
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;		
	
	//Разрываем соединение
	session.Dispose();

Все необходимые файлы и пример обработки обмена во вложении.

Я привел пример только основных возможностей, которые сам использовал. У библиотеки довольно много классов и методов и при необходимости возможности использования можно значительно расширить. Мануал здесь

Пример работы с WinSCP через командную строку

Скачать файлы

Наименование Файл Версия Размер
ЗагрузкаВыгрузкаНаSFTP.epf
.epf 7,69Kb
29.07.13
85
.epf 7,69Kb 85 Скачать
winscp515.zip
.zip 3,67Mb
29.07.13
30
.zip 3,67Mb 30 Скачать
winscp515automation.zip
.zip 41,19Kb
29.07.13
31
.zip 41,19Kb 31 Скачать

См. также

Комментарии
1. Сергей Маслов (LexSeIch) 180 31.07.13 11:10 Сейчас в теме
Мир этому дому!
Спасибо за интересную информацию - взял на заметку. Отдельное спасибо за ссылки по теме - будем разбираться.
krosaf4eg; ram3; +2 Ответить
2. Владислав (Vladuha) 31.07.13 12:08 Сейчас в теме
Так ведь 8.3 умеет ЗащищенноеСоединениеOpenSSL
3. Ramz # (ram3) 103 31.07.13 12:32 Сейчас в теме
Да действительно, заявлено что 8.3 умеет устанавливать FTPСоединение по SSL, не пробовал. Я привел рабочий пример для 8.2. Спасибо за информацию
4. Василий Казьмин (awk) 668 31.07.13 17:39 Сейчас в теме
(2) Vladuha, SFTP и FTPS - это разные вещи. SFTP - это фтп ssh сервера, а FTPS - это фтп через SSL/TLS.
krosaf4eg; kashafeev; ram3; +3 Ответить 2
5. Владислав (Vladuha) 31.07.13 17:48 Сейчас в теме
(4) awk, ваша правда, перепутал
6. Ivan Khorkov (vano-ekt) 816 01.08.13 15:37 Сейчас в теме
норм, а я когда-то лет 7 назад для 8.1 настраивал какого-то ftp-клиента на сервере, прописывал профили, а потом вызывал через КомандаСистемы...
COM - это хорошо
а 8.3 - лучше :)
7. Ivan Khorkov (vano-ekt) 816 01.08.13 15:39 Сейчас в теме
(4) о я тоже думал 8.3 SSL научили, а там тунели запилили
8. Ramz # (ram3) 103 02.08.13 14:53 Сейчас в теме
(6) vano-ekt,
Как выяснилось, 8.3 тоже не умеет работать с SFTP
9. Александр Кулешов (Aragorn) 13.08.13 16:01 Сейчас в теме
Спасибо, свое время тоже пришлось поизвращатся с sftp
10. Денис Попов (d_control) 3 27.01.14 16:33 Сейчас в теме
Добрый день!
Очень благодарен за информацию!

Только у меня не получается подключиться.
Не пойму что нужно указать в поле "SshHostKeyFingerprint"
где взять значение для этого поля?

Через обычного клиента WinSCP подключаюсь нормально. Там просто указываю адрес, юзера и пароль.
11. Денис Попов (d_control) 3 27.01.14 16:40 Сейчас в теме
Всё, нашел... прошу прощения за неумный вопрос :)
12. Ийон Тихий (cool.vlad4) 41 27.01.14 16:53 Сейчас в теме
http://habrahabr.ru/company/Centrobit/blog/165441/
Вывод: данная реализация позволяет передавать файлы из 1С: Предприятие 8.2. большого размера по защищенному протоколу SFTP. Плюс появляется возможность переносить часть функционала из 1С во внешнюю компоненту, что защищает написанный код и позволяет реализовывать дополнительный, не доступный 1С функционал.

исходники открыты.
borodatii; +1 Ответить
13. Иван (John83) 26.05.14 16:49 Сейчас в теме
Установил приложение, зарегил библиотеку, но все равно при попытке создать COM-объект в 1С, ругается
{Форма.Форма.Форма(17)}: Ошибка при вызове конструктора (COMОбъект): Класс не зарегистрирован: Класс не зарегистрирован
Кто-нибудь сталкивался?
14. Ramz # (ram3) 103 26.05.14 17:47 Сейчас в теме
15. Rauan Sandybaev (sandybaev) 8 28.08.14 14:50 Сейчас в теме
16. Rauan Sandybaev (sandybaev) 8 29.08.14 07:00 Сейчас в теме
Ребята, а что таки писать в поле sessionOptions.SshHostKeyFingerprint ?

я вот пишу так:

sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 67:13:89:75:aa:5f:b4:9b:e2:f2:da:87:41:a1:d2:d1";


система мне отвечает так:
Соединение неожиданно разорвано. Сервер вернул код завершения команды 0.

вот от куда беру код:


Прикрепленные файлы:
17. Ramz # (ram3) 103 29.08.14 11:38 Сейчас в теме
(16) sandybaev,
какая именно команда возвращает ошибку, .Open ? С этими же параметрами через саму программу подключиться удается?
18. Rauan Sandybaev (sandybaev) 8 02.09.14 06:57 Сейчас в теме
(17) ram3, Все, брат. Получилось. В параметр SshHostKeyFingerprint Я передал публичный ключ сгенерированный самим sftp серваком. А ошибка подключения была в изменненом пароле администратора (я об этом узнал потом).

Огромное спасибо вроде все заработало.

ТОлько единственное не пойму зачем ты перемещаешь файл этой командой -
ПереместитьФайл(ВыгруженныйФайл.FileName, ХранилищеВыгруженныхФайлов);

Если на сервер ты уже закидываешь эти файлы командой

session.PutFiles(ПутьВыгрузки, ПутьЗагрузкиНаФТП); ?

19. Ramz # (ram3) 103 02.09.14 09:53 Сейчас в теме
(18) sandybaev,
.PutFiles это выгрузка на сервер, а мне еще нужно было сохранять локально все успешно выгруженные файлы, поэтому я сначала проверял результат .Check() , а потом в цикле по коллекции результатов выгрузки сохранял эти же файлы локально, для истории
20. Rauan Sandybaev (sandybaev) 8 05.09.14 06:10 Сейчас в теме
21. Rauan Sandybaev (sandybaev) 8 08.09.14 13:21 Сейчас в теме
(19) ram3,
Не подскажешь.
Как теперь я могу создавать и менять папки на sftp серваке.
Просто тут пишу обработку для обмена а она по ТЗ должна уметь создавать и менять папки.

Заранее спасибо.
22. Ramz # (ram3) 103 08.09.14 16:10 Сейчас в теме
(21) sandybaev,
создавать - CreateDirectory, читай мануалы http://winscp.net/eng/docs/library_session , думаю там все найдешь.
и плюсани уж за публикацию)
23. Rauan Sandybaev (sandybaev) 8 10.09.14 08:06 Сейчас в теме
(22) ram3, Все, плюсанул вроде как. Почитаю на досуге. Спасибо большое. Тебе бы дальше эту тему развить. желательно с обилием скринов :)
24. Роберт Рождественский (kashafeev) 11.09.14 05:16 Сейчас в теме
(22) ram3, отличная публикация! Есть вопрос по такой задаче: необходимо синхронизировать файлы командой SynchronizeDirectories. Пишу:

transferResult = session.SynchronizeDirectories(Local, ПутьЗагрузкиЛокальный, ПутьКФайламНаСервере, Ложь, Ложь, , "*.wav");

Но не знаю, что ставить в первый параметр. По-идее, там должен быть класс SynchronizationMode mode (Например: SynchronizationMode.Local, SynchronizationMode.Remote and SynchronizationMode.Both).

Как его объявить в 1С?
25. Ramz # (ram3) 103 11.09.14 11:49 Сейчас в теме
(24) kashafeev,
думаю можно так:
SynchronizationMode = Новый COMОбъект("WinSCP.SynchronizationMode");

но не уверен, надо пробовать.
26. Роберт Рождественский (kashafeev) 11.09.14 09:51 Сейчас в теме
(25) ram3, пробовал, не получилось. Есть ещё какие-нибудь предложения?
27. Ramz # (ram3) 103 11.09.14 12:27 Сейчас в теме
(26) kashafeev,
а так:
WinSCP = Новый COMОбъект("WinSCP");
SynchronizationMode = WinSCP.SynchronizationMode;

мне это не нужно было, сейчас к сожалению времени нет разбираться. Посмотри примеры на сайте разработчика, может что найдешь
28. Евгений (Пользователь 1С) 2 22.09.14 19:51 Сейчас в теме
Для 7.7 нечто подобное реально?
29. Ramz # (ram3) 103 25.09.14 11:11 Сейчас в теме
(28) Пользователь 1С, почему нет? С COM Объектами 7.7 вроде как умеет. Код только немного переписать
30. krosaf4eg (krosaf4eg) 44 30.10.14 01:55 Сейчас в теме
спасибо за чудесную реализацию!!!
в сети навалом обработок, но все они работают через командную строку, а тут COM-соединение. То что доктор прописал )))) в благодарность скачал, хотя и качать ничего не нужно, все понятно из текста статьи
31. Ризван Шихамматов (dagroma) 110 03.11.14 13:25 Сейчас в теме
(26) kashafeev,
SynchronizationMode mode: 0 - local, 1 - remote, , 2 - both
SynchronizationCriteria criteria: 0 - None, 1 - Time, 2 - Size, 3 - Either
32. Alexandr Surkov (basta-one2007) 27.01.15 19:34 Сейчас в теме
Спасибо большое. Статья очень помогла.
33. Rauan Sandybaev (sandybaev) 8 10.02.15 15:09 Сейчас в теме
ребята помогите
есть коренвая директория сервера /public

в ней я программно создаю поддиректорию командой session.CreateDirectory("/public" + "ОбластьКонтрагента")

все ок, создается теперь надо дальше в директории области контрагента создать еще одну папку (последнюю) под названием "НаименованиеКонтрагента"

как это сделать через функции WinSCPnet.dll?

перерыл из форум и хэлп, ничего нет.
34. vadim anonim (ferre) 17.07.15 12:11 Сейчас в теме
Помогите
Как подключится без пароля с приват ключем.

sessionOptions = Новый COMОбъект("WinSCP.SessionOptions"); //Создаем объект SessionOptions
sessionOptions.HostName = "1.1.1.1";
sessionOptions.UserName = "log";
//sessionOptions.Password = "mypassword";
sessionOptions.PortNumber = "22";
sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 010101010110101001012010";
sessionOptions.SshPrivateKeyPath = "С:\1111.ppk";

session = Новый COMОбъект("WinSCP.Session"); //Создаем объект Session
//параметр необходимо использовать если пути регистрации DLL и исполняемого файла различны
session.ExecutablePath = "C:\Program Files (x86)\WinSCP\winscp.exe";

// Подключаемся
session.Open(sessionOptions);

Ошибка:
{Обработка.Обработка1.Форма.Форма.Форма(20)}: Ошибка при вызове метода контекста (Open): Произошла исключительная ситуация (WinSCPnet): Disconnected: No supported authentication methods available (server sent: publickey)
35. Александр Синиченко (nytlenc) 30 12.02.16 09:18 Сейчас в теме
(34) ferre, файл ключ с паролем?
36. Александр Синиченко (nytlenc) 30 12.02.16 09:18 Сейчас в теме
(34) ferre, если да то добавь sessionOptions.SshPrivateKeyPassphrase = "ТвойПарольНаКлюч";
37. Dimka 74 (Dimka74) 09.04.16 22:29 Сейчас в теме
Коллеги, подскажите как зарегистрировать WinSCP.dll, дело в том, что я в принципе такого файла найти не могу, нашел WinSCPnet.dll.
Зарегистрировал библиотеку командой

%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe WinSCPnet.dll /codebase /tlb

в ответ получил

Типы зарегистрированы успешно
Сборка экспортирована в "C:\Windows\system32\WinSCPnet.tlb"; библиотека типов зарегистрирована успешно


Пытаюсь соединиться по sftp, 1 ска выдает ошибку:
{ОбщийМодуль.МойМодуль.Модуль(296)}: Ошибка при вызове конструктора (COMОбъект): -2147221164(0x80040154): Недопустимая строка с указанием класса


Что не так сделано?
38. Ramz # (ram3) 103 11.04.16 11:23 Сейчас в теме
(37) Dimka74,
Коллеги, подскажите как зарегистрировать WinSCP.dll, дело в том, что я в принципе такого файла найти не могу, нашел WinSCPnet.dll.

(37) Dimka74, в статье описание для версии 515, возможно сейчас что-то изменилось. Здесь есть вся информация по установке и регистрации http://winscp.net/eng/docs/library_install#registering
39. Dimka 74 (Dimka74) 11.04.16 20:50 Сейчас в теме
(38) Спасибо за ответ, от туда информацию и черпал.
Может быть теперь ошибка в коде 1с?
Если изменилась библиотека, быть может теперь надо и код 1с править?
Например раньше надо было так:
sessionOptions = Новый COMОбъект("WinSCP.SessionOptions"); //Создаем объект SessionOptions

а сейчас надо так:
sessionOptions = Новый COMОбъект("WinSCPnet.SessionOptions"); //Создаем объект SessionOptions


Хотя может быть мои знания устарели, и передача файла по SFTP в 1с возможна без лишних плясок - напрямую из платформы?
40. Ramz # (ram3) 103 12.04.16 10:05 Сейчас в теме
(39) Dimka74,
Может быть теперь ошибка в коде 1с?
Если изменилась библиотека, быть может теперь надо и код 1с править?

Я бы не стал называть это ошибкой, с версией 515 все работает. Если хотите использовать свежую версию, возможно придется адаптировать код. В заголовке статьи написано ПРИМЕР, это не готовое решение на все времена, и пожизненную поддержку никто не обещал.
Хотя может быть мои знания устарели, и передача файла по SFTP в 1с возможна без лишних плясок - напрямую из платформы?

На сколько я знаю, платформа 1С пока не поддерживает sFTP, только FTPS.

41. A2O2tqaOo8Hn 27CDHsRBnQbc (shved) 13.08.16 08:26 Сейчас в теме
что значит ошибка:
{ВнешняяОбработка.WinSCP.Форма.Форма.Форма(51)}: Ошибка при вызове метода контекста (Open): Произошла исключительная ситуация (WinSCPnet): Алгоритм обмена ключей diffie-hellman-group1-sha1 не был проверен!

как проверить алгоритм?
42. A2O2tqaOo8Hn 27CDHsRBnQbc (shved) 13.08.16 08:30 Сейчас в теме

при подключение оболочкой спрашивает про тоже самое, но тут можно нажать ДА и все ок.
а как нажать Да через КОМ-соединение?
43. A2O2tqaOo8Hn 27CDHsRBnQbc (shved) 13.08.16 08:58 Сейчас в теме
в оболочке нашел как сдвинуть свой алгоритм наверх.
но как в ком... пока ищю
добавил в парамтерах сессии
bool GiveUpSecurityAndAcceptAnyTlsHostCertificate Give up security and accept any FTPS/WebDAVS server TLS/SSL certificate. To be used in exceptional situations only, when security is not required. When set, log files will include warning about insecure connection. To maintain security, use TlsHostCertificateFingerprint.
но не помогло
Прикрепленные файлы:
44. A2O2tqaOo8Hn 27CDHsRBnQbc (shved) 13.08.16 10:06 Сейчас в теме
версия последняя на седня 5.9.1. так и не победил.
искать старые может. в них видимо такой проверки не было
45. A2O2tqaOo8Hn 27CDHsRBnQbc (shved) 16.08.16 21:16 Сейчас в теме
победил!
sessionOptions.AddRawSettings("Cipher", "des,aes,chacha20,blowfish,3des,arcfour,WARN");
sessionOptions.AddRawSettings("KEX", "dh-group1-sha1,ecdh,dh-gex-sha1,dh-group14-sha1,rsa,WARN");

46. Константин Золотов (KokaDu) 12.10.16 22:36 Сейчас в теме
Коллеги, после установки 1С платформы 8.3.9 и обновления WinSCP на 5.9.2 у меня просто "Неизвестная ошибка"
{ВнешняяОбработка.ЗагрузкаФайлаСFTPСервера.Форма.Форма.Форма(92)}: Ошибка при вызове метода контекста (Open)
session.Open(sessionOptions);
по причине:
Неизвестная ошибка
Даже и не знаю куда копать. Может кто подскажет?
47. Ramz # (ram3) 103 13.10.16 15:06 Сейчас в теме
(46) KokaDu, два варианта: либо качать старую версию WinSCP, либо смотреть документацию по новой версии и менять вызов метода .Open, видимо здесь "sessionOptions" что-то не соответствует новой версии.
Уже были проблемы с новой версией выше в комментариях. Я с WinSCP уже давно не работаю, проверить к сожалению не могу...
48. Константин Золотов (KokaDu) 14.10.16 13:48 Сейчас в теме
(47) ram3, перерыл документацию, ничего нового по "Open" не нашел.
Проблему обошел тем, что создал bat-ник из самого WinSCP , который запускается из 1С.
В любом случае спасибо.
49. Павел Буйновский (Bujnovskij_Pavel) 26.10.16 13:25 Сейчас в теме
Спасибо большое!! Очень помогли
50. Никита Ефремов (Shooroopik111) 116 02.02.17 19:02 Сейчас в теме
(48)
(47) ram3, перерыл документацию, ничего нового по "Open" не нашел.
Проблему обошел тем, что создал bat-ник из самого WinSCP , который запускается из 1С.
В любом случае спасибо.

Проблема ошибки OPEN встала очень остро.
Переход на старую версию не помог. ВЫявил следующую закономерность: при простой регистрации компоненты через командную строку и работе на клиенте все ок.
Как только регистрируем компоненту в службе компонентов чтоб работало на серваке- ловим ошибку OPEN. Может быть кто то победил ее?
51. Константин Золотов (KokaDu) 03.02.17 08:39 Сейчас в теме
Сделайте батник по работе с WinSCP, пример во вложении.
Прикрепленные файлы:
PutSFTP.txt
52. Анатолий (ABudnikov) 1 13.03.17 17:15 Сейчас в теме
(50) столкнулся с такой же проблемой. Вам удалось победить регистрацию WinSCP для работы на сервере?
53. Константин Золотов (KokaDu) 13.03.17 20:51 Сейчас в теме
После регистрация WinSCP как 64 битного приложения проблема с OPEN остаётся.

Предлагаю следующие варианты решения с использованием батника:
Во вложении примеры с получением и отправки файла.

У меня есть еще решение с использованием Putty, если будет интересно, тоже могу поделиться.
Прикрепленные файлы:
GetSFTP.txt
PutSFTP.txt
54. A2O2tqaOo8Hn 27CDHsRBnQbc (shved) 13.03.17 21:22 Сейчас в теме
коллеги, у меня длл регается как
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm.exe WinSCPnet.dll /codebase /tlb:WinSCPnet.tlb
сама длл тут https://winscp.net/download/WinSCP-5.9.4-Automation.zip

далее
sessionOptions = Новый COMОбъект("WinSCP.SessionOptions"); //Создаем объект SessionOptions
		sessionOptions.HostName 				= "192.168.0.1";
		sessionOptions.UserName 				= "порно";
		sessionOptions.Password 				= "секс";
		sessionOptions.PortNumber 				= 22;
		sessionOptions.SshHostKeyFingerprint 	= "ssh-rsa 1024 7d:43:b7:43:05:30:01:3a:9f:e6:75:d8:29:e6:ca:fd";
		
		sessionOptions.AddRawSettings("Cipher", "des,aes,chacha20,blowfish,3des,arcfour,WARN");
		sessionOptions.AddRawSettings("KEX", "dh-group1-sha1,ecdh,dh-gex-sha1,dh-group14-sha1,rsa,WARN");
		
        session = Новый COMОбъект("WinSCP.Session"); //Создаем объект Session
	
		// Подключаемся
		session.Open(sessionOptions);
...Показать Скрыть


далее послать принять как обычно

ПС вин2008р2 64. 1с8*64
55. Анатолий (ABudnikov) 1 14.03.17 09:10 Сейчас в теме
(54) Спасибо. Заработало. Только я последовательно выполнил
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe WinSCPnet.dll /codebase /tlb:WinSCPnet32.tlb
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe WinSCPnet.dll /codebase /tlb:WinSCPnet64.tlb
на всякий случай чтоб в двух вариантах работало.
И всё заработало.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа