Во время создания очередной B2B-системы на этапе интеграции 1С: Предприятие 8.2 с web — интерфейсом возникла необходимость безопасной передачи файлов больших размеров из 1С в web.
Для решения этой задачи был выбран протокол SFTP, как надежный и не имеющий ограничений по размеру передаваемого файла.
Во встроенном языке 1С: Предприятие 8.2 отсутствуют функции для передачи данных через SFTP, поэтому пришлось искать прикладные средства. На интернет-ресурсах, посвященных программированию 1С, есть примеры удачного использования freeware утилит типа WinSCP. Для использования данного способа необходимо из встроенного языка 1С выполнить запуск утилиты с параметрами командной строки.
Пример запуска утилиты WinCSP из 1С:
КомандаВыгрузки = Символ(34)+Строка(ПутьКПапкеХранилищаФТПФайлов)+"\"+ "WinSCP.com"+Символ(34)+"/script="+Символ(34)+Строка(ПутьКПапкеХранилищаФТПФайлов)+Символ(34)+"\script.txt "+"/parameter "+Символ(34)+Адрес+Символ(34)+" "+ Символ(34)+Ключ+Символ(34)+" "+Символ(34) + Подпапка + Символ(34) + " " + Символ(34) + ИмяФайлаОтправки + Символ(34);
Минусом такого решения является отсутствие возможности контроля ошибок запуска и выполнения из встроенного языка 1С. В связи с этим было принято решение написать внешнюю DLL компоненту для 1С: Предприятие 8.2.
Платформа 1С: Предприятие поддерживает две технологии создания внешних компонент Native API и COM. Выбор пал на Native API, так как компоненты, созданные по этой технологии работают как на клиенте, так и на сервере 1С. Используя материалы диска ИТС о технологии создания внешних компонент и open source библиотеки С++, был создан файл SftpExtension.dll (Скачать исходники можно тут).
Создание компоненты DLL
1. Для использования в компоненте протокола SFTP мы использовали две библиотеки.
— libssh http://www.libssh2.org/ (Скачиваем “git clone git://git.libssh2.org/libssh2.git”)
— openssl http://www.openssl.org/ (Скачиваем архив openssl-1.0.1c.tar.gz от сюда)
Подключаем библиотеки к проекту.
2. Каждый объект компоненты должен наследоваться от абстрактного класса IcomponentBase и IlanguageInterface.
- IcomponentBase — реализует основные методы компоненты.
- IlanguageInterface — служит для локализации методов и свойств 1С и С++ через определения массивов соответствий и методов акцессоров GetMethodName, GetPropName.
Часть кода компоненты описывающая возможность вызова функций С++ из 1С на русском языке:
При этом можно использовать другие языки.
static wchar_t *g_MethodNames[] = { L"SendFile",L"StartSession", L"EndSession", L"IsSessionStart",L"SetSshHost",L"SetSshLogin",L"SetSshPass",L"SetSftpPath",L"SetLocalPath"}; static wchar_t *g_MethodNamesRu[] = { L"ПослатьФайл",L"НачатьСессию",L"ЗакончитьСессию",L"ЕслиСессияНачата", L"УстановитьХост",L"УстановитьЛогин",L"УстановитьПароль", L"УстановитьУдаленныйПуть",L"УстановитьЛокальныйПуть"}; const WCHAR_T* SftpExtension::GetMethodName(const long lMethodNum, const long lMethodAlias) { if (lMethodNum >= eMethLast) return NULL; wchar_t *wsCurrentName = NULL; WCHAR_T *wsMethodName = NULL; int iActualSize = 0; switch(lMethodAlias) { case 0: // First language wsCurrentName = g_MethodNames[lMethodNum]; break; case 1: // Second language wsCurrentName = g_MethodNamesRu[lMethodNum]; break; default: return 0; } iActualSize = wcslen(wsCurrentName)+1; if (m_iMemory && wsCurrentName) { if(m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize); } return wsMethodName; }
3. Для вызова необходимой функции из компоненты используется метод CallAsFunc из интерфейса IcomponentBase. При вызове методов из компоненты 1С, вызывается этот С++ метод.
В качестве параметров метода используются:
- lMethodNum – номер метода в массиве соответствий.
- pvarRetValue – указатель на выходные параметры.
- paParams — параметры из метода в 1С.
- lSizeArray – размер массива, если входной параметр массив.
bool SftpExtension::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue,tVariant* paParams, const long lSizeArray){ switch(lMethodNum){ case eMethSendFile: { if (!lSizeArray || !paParams) return false; this->local_path = toChar(paParams); WriteToServer(status, this->local_path); // pvarRetValue->pstrVal = status; //status pvarRetValue->strLen = strlen(pvarRetValue->pstrVal); TV_VT(pvarRetValue) = VTYPE_PSTR; ret = true; break; } } return ret; }
4. В нашем примере из 1С можно выполнять 4 метода, которым соответствуют С++ методы в DLL компоненте.
1С (методы) | С++ методы |
---|---|
НачатьСессию() Предварительно нужно определить параметры авторизации(хост, связку логин, пароль – либо rsa ключи, путь на удалённом сервере). Поэтому функция НачатьСессию обрастает свойствами: Хост, Логин, Пароль, УдаленныйПуть |
StartSSHSession(status,this->ssh_host,this->ssh_login,this->ssh_pass); StartSftpSession(status,this->sftp_path) |
ПослатьФайл(“Путь и имя файла на клиентской машине”) | WriteToServer(const char * &status, const char *loclfile) |
ЕслиСессияНачата() | isSessionStart() |
ЗакончитьСессию() | endSession() – завершает SFTP сеанс и SSH сеанс |
5. В С++ нужно определить параметры доступа(чтение/запись) к созданным свойствам за это отвечают два метода IsPropReadable и IsPropWritable.
bool SftpExtension::IsPropReadable(const long lPropNum) { switch(lPropNum) { case ePropSshHost: return true; default: return false; } return false;}
Таблица соотношений свойств 1С и С++
1С(свойства) | С++ свойства |
---|---|
Хост | ssh_host |
Логин | ssh_login |
Пароль | ssh_pass |
УдаленныйПуть | Sftp_path |
Готовую библиотеку можно скачать тут.
Работа с компонентой во встроенном языке 1С
1. Выполняем подключение и создаем объект внешней компоненты, с помощью стандартных команд встроенного языка 1С.
ПодключитьВнешнююКомпоненту("C:\SftpExtension\SftpExtension.dll","Компонента",ТипВнешнейКомпоненты.Native); Компонента = Новый("AddIn.Компонента.SftpExtension");
2. Заполняем 4 свойства объекта компоненты Хост, Логин, Пароль, УдаленныйПуть.
Компонента.Хост = "192.168.0.1"; Компонента.Логин = "root"; Компонента.Пароль = "123"; Компонента.УдаленныйПуть = "/var/www/company/data/www/import/data.xml";
3. Открываем сессию соединения
Компонента.НачатьСессию();
4. Отправляем файл
Компонента.ПослатьФайл("C:\data.xml");
5. Отправляем следующий файл, с проверкой открыта ли сессия соединения.
Если Компонента.СессияНачата() Тогда Компонента.ПослатьФайл("C:\data2.xml"); Иначе Компонента.НачатьСессию(); Компонента.ПослатьФайл("C:\data2.xml"); КонецЕсли;
6. После отправки файлов закрываем сессию
Компонента.ЗакончитьСессию();
В результате выполнения успешно был передан файл с C:\data2.xml в /var/www/company/data/www/import/data.xml.
Используемые материалы
Литература:
Мануал по созданию компоненты
Библиотеки для работы по SFTP:
- libssh http://www.libssh2.org/
- openssl http://www.openssl.org/
Вывод: данная реализация позволяет передавать файлы из 1С: Предприятие 8.2. большого размера по защищенному протоколу SFTP. Плюс появляется возможность переносить часть функционала из 1С во внешнюю компоненту, что защищает написанный код и позволяет реализовывать дополнительный, не доступный 1С функционал.
ссылка на оригинал статьи http://habrahabr.ru/company/Centrobit/blog/165441/
Добавить комментарий