Опыт передачи файлов большого объема по защищенному протоколу из 1С на сайт

    передача файлов большого объема по защищенному протоколу из 1С на сайт
    Во время создания очередной 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:


    Вывод: данная реализация позволяет передавать файлы из 1С: Предприятие 8.2. большого размера по защищенному протоколу SFTP. Плюс появляется возможность переносить часть функционала из 1С во внешнюю компоненту, что защищает написанный код и позволяет реализовывать дополнительный, не доступный 1С функционал.
    CentroBit
    Company
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 13

      0
      wscript.shell позволяет stdout и код возврата мониторить.
        0
        Изучим, спасибо.
          0
          Молодцы, что прорвались.

          Только вопрос, а не проще было использовать модифицированный протокол 1С-сайт через HTTPS? (модифицировать правда придется самим).
          Протокол позволяет передавать файлы любой длины со сжатием и без, с контролем передачи и без. минус подхода, придется писать серверную часть с контролем немалого количества нюансов.
          Если будет интересно, могу на выходных разродится статьей на эту тему.

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

          Ну и третий из возможных подходов, приходящих на ум сразу, это использование WinHTTP или ему подобных компонент.

          Не могли бы вы рассказать, что именно оказалось определяющим в выборе пути решения.

          Ссылки:
          Протокол передачи данных 1С-сайт (в очень не полном изложении 1С)

          Подключение сертификата к 1С 8.х

          WinHTTP

            0
            Попробую ответить:

            1) Почему не через модифицированный протокол 1С-сайт через HTTPS?
            На этот вопрос вы сами отчасти ответили.
            (модифицировать правда придется самим)

            Честно не изучали этот вопрос и ваша будущая статья представляет интерес.

            2) Почему не WinHTTP либо Wget?
            Долгое время пользовались WinSCP. Дергали с параметрами внешний exeшник который передавайл файлы на сайт. В какой-то момент столкнулись с проблемой при передачи большого числа файлов. Создавалось много WinSCP процессов, которые подвешивали сервер 1С. В итоге пришли к идеи поточной реализации. Внутри потока передаются файлы.

            Это наш код которым можно управлять, можно модифицировать и который мы знаем как устроен.

            Еще раз:
            — можно ли было добиться того же эффекта другими способами?
            — Да можно.

            Данный пост не об многообразии протоколов и их оберток (Webdav, например). Берите любой! Но когда нужно гибко управлять кодом — изучение и использование технологии внешних компонент стало для нас выходом.

              0
              Под POST запросы на WEB сервере нужно выделять память. 20МБ, 30МБ — 100МБ. Хорошо если знаешь какого максимального размера будут файлы. Но если не знаешь — выделять на web сервере размер в 1GB — является потенциальной проблемлй безопасности. Нет никаких гарантий что кто-то другой, кроме 1С не начнет постить файлы. И делать это из формы на сайте
                0
                Бр-бр-бр. Я говорил не о модификации сервера 1С-Предприятия, я говорил о модификации WEB-сервера.
                Ответчик придется писать (ну точнее приемщик частей файлов и сборку окончательного файла. У 1С так устроен протокол передачи.)

                Выделение памяти не страшно, так как ответчик на веб-сервере может регламентировать максимальный размер посылки, а 1С умеет разбивать файлы при их пересылке.

                Если интересует как устроено, посмотрите обработку «Обмен с сайтом» и общий модуль «ПроцедурыОбменаССайтом» в конфигурации Торг 10.3, они по функционалу недалеки от такой же подсистемы в Торг 11, но проще для анализа.

                Подбивая бабки:

                1. Нужен HTTPS сервер с валидным сертификатом
                2. Нужно уметь работать с сертификатами в 1С (ссылка выше)
                3. Нужно модифицировать обработку «Обмен с сайтом», сделать ее внешней, перенести в нее процедуры «Послать на сайт()» и «Принять с сайта()» из «ПроцедурыОбменаССайтом», и перезаточить их на работу с HTTPS.
                4. Нужно на стороне веб-сервера написать ответчик-приемщик файлов

                Зачем это делать:

                1. Идеологически вы остаетесь в пространстве реализаций 1С и Битрикс
                2. Непосредственно в ответчик-приемщик можно вставлять дополнительные обработки файла по событию «Передача файла завершена»
                3. Это решение не зависит от операционной системы, на которой запущен 1С-ВебКлиент (dll в линуксах будет чувствовать себя не очень уютно)

                Почему это не надо делать:

                1. Придется ковырять веб-сервер (а он может быть совсем в чужой зоне ответственности)
                2. Если в команде только 1С-програмисты, то серверное програмирование придется заказывать на стороне
                3. Система состоит из двух компонент, что хуже системы состоящей из одной компоненты. (если все максимально упрощать, и функционал sshd(sftp) считать априори надежным и безошибочным)

                Ну а дальше вам решать :)

                П.С. Наверняка забыл какие-то плюсы и минусы, но основные вроде перечислил.

                П.П.С. Ни в коем случае не утверждаю, что ваше решение нехорошо. Просто есть и другие варианты.
                  0
                  Просто увидел тег Битрикс, и мне показалось, наверное безосновательно, что обмен шел именно с Битрикс-системой.
                    0
                    Есть еще один минус.

                    Придется разбираться с протоколом передачи 1С-Сайт, который, к сожалению, не всегда отличается полнотой (Полную транзакцию придется реализовывать самому ручками) и не вполне очевиден в некоторых местах.

                    Но так как все равно придется допиливать процедуры «Послать» и «Принять», то это не есть совсем уж существенные гадости.
                      0
                      Обмен шел с нашей системой. К Битриксу не имеем никакого отношения.
                0
                Похоже что ссылка на исходники не работает :(
                  0
                  К сожалению, ребята написали, что исходники и компонента у них не сохранились
                    0
                    Ну и ладно, написал свою уже :)
                      0
                      А вы не могли бы ее выложить где-нибудь, пожалуйста? Если можно — с исходниками

                Only users with full accounts can post comments. Log in, please.