Интеграция DIRECTUM с порталами по протоколу FTP

8 4

Предположим, что есть портал, на котором формируется какая-то информация (например, обращение гражданина) в определенном xml-формате. Необходимо эту информацию импортировать в систему DIRECTUM, обработать и результат вернуть обратно на портал тоже в определенном xml-формате. Связь с порталом возможна только по протоколу FTP.

Возможные варианты реализации обмена с порталом:

  1. Использовать программное обеспечение предоставляющее доступ к FTP ресурсам как к обычной сетевой папке.
  2. Использовать сторонние dll, содержащие функции обмена по протоколу FTP.
  3. Использовать сторонние COM-объекты (ActiveX-компоненты), предоставляющие возможности обмена по протоколу FTP.

На первый взгляд, первый вариант выглядит наиболее предпочтительным.  Доступ к FTP ресурсам осуществляется как к обычной сетевой папке, а работа с сетевыми папками в DIRECTUM никаких сложностей не вызывает. Из бесплатных программ, реализующих эту функцию, мне попалась только FTPDrive, которая, судя по отзывам на форумах, не отличалась особой стабильностью. В результате от её использования пришлось отказаться. Также, возможно, подключить FTP ресурс как сетевой диск средствами Windows без использования стороннего программного обеспечения. Данный вариант реализации рассматривать не будем. Если выбирать между вторым и третьим вариантом реализации, то я бы выбрал именно третий вариант, так как он удобнее и проще в реализации.

Для реализации третьего варианта можно использовать свободно распространяемый COM-сервер Chilkat Ftp. Данная компонента распространяется бесплатно для коммерческого и некоммерческого использования. Разработчиком компоненты является Chilkat Software. Чтобы использовать возможности Chilkat FTP, его необходимо установить на рабочее место на котором будет выполняться обмен с порталом.

Бесплатный COM-сервер Chilkat FTP позволяет:

  • копировать файлы с/на ftp-сервер;
  • копировать файлы с/на ftp-сервер непосредственно из памяти;
  • создать каталоги, переименовать/удалить файлы/каталоги на ftp-сервере;
  • получить листинг каталога на ftp-сервере в виде XML;
  • работать с протоколом FTP в пассивном режиме.

Компонента доступна для скачивания на странице  загрузки проекта или по прямой ссылке Chilkat FTP.

Пример копирования файлов с FTP-сервера:

  MsgTemplate = "%2:s%1:s%3:s%1:s%4:s%1:s%5:s%0:s"
  // Путь до файла логов
  LogFileName = GetTempFolder()&"\DIRECTUM_ErrorImport.log"
  // Папка для входящих xml-файлов
  PathInput = "C:\Directum\In\"

// ----------------- Начало обмена с порталом по FTP протоколу -----------------

  // Создадим объект ChilkatFTP для обмена по FTP протоколу
  FreeException()
  ExceptionsOff()
  Ftp = CreateObject("ChilkatFTP.ChilkatFTP")
  ExceptionsOn()
                                                                               
  // Если при создании объекта была ошибка
  if ExceptionExists() 
    Error = GetLastException()
    // Ошибка при создании объекта ChilkatFTP. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Ошибка при создании объекта ChilkatFTP. Подробнее: "&Error.Message)))      
    FreeException()
    Прервать()
  endif 

  // Адрес портала
  Ftp.Hostname = PortalHostName
  // Логин  
  Ftp.Username = PortalUserName
  // Пароль  
  Ftp.Password = PortalPassword
  // Порт  
  Ftp.Port = PortalPort
  // Пассивный режим обмена  
  Ftp.Passive = 1                

  // Соединимся с FTP-сервером портала
  Success = Ftp.Connect()
  // Если соединиться не удалось
  if (Success <> 1)
    // Ошибка соединения с FTP-сервером портала. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Ошибка соединения с FTP-сервером портала. Подробнее: "&Ftp.LastErrorText)))      
    Прервать()
  endIf
  
  // Перейдем в корневой каталог 
  Success = Ftp.ChangeRemoteDir(PortalRootDir)
  // Если перейти не удалось
  if (Success <> 1)
    // Не удалось перейти в корневой каталог. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Не удалось перейти в корневой каталог. Подробнее: "&Ftp.LastErrorText)))      
    Прервать()
  endif

  // Получим структуру папок и файлов
  Ftp.ListPattern = "*"

  // Количество файлов в папке
  NumFileCount = Ftp.NumFilesAndDirs
  // Если не удалось прочитать структуру каталога
  if (NumFileCount < 0)
    // Ошибка чтения структуры файлов и папок. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Ошибка чтения структуры файлов и папок. Подробнее: "&Ftp.LastErrorText)))      
    Прервать()
  endIf
  
  if NumFileCount > 0
    NumFileCur = 0
    while NumFileCur < NumFileCount
      RemoteFileName = Ftp.GetFilename(NumFileCur)
        // Обрабатываем только файлы
        if (Ftp.GetIsDirectory(NumFileCur) = 0)
            LocalFileName = PathInput&RemoteFileName
            Success = Ftp.GetFile(RemoteFilename; LocalFilename)
            // Если загрузить не удалось
            if (Success <> 1)
              // Не удалось загрузить файл с FTP-сервера. Подробнее:  
              ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                          ArrayOf(CR; TAB; Today(); Time(); RemoteFilename; 
                          "Не удалось загрузить файл с FTP-сервера. Подробнее: "&Ftp.LastErrorText)))      
              Прервать()
            endif
        endif
      NumFileCur = NumFileCur + 1
    endwhile
  endif  
  Ftp.Disconnect
// ----------------- Конец обмена с порталом по FTP протоколу  -----------------

Пример копирования файла на FTP-сервер:

  MsgTemplate = "%2:s%1:s%3:s%1:s%4:s%1:s%5:s%0:s"
  LogFileName = GetTempFolder()&"\DIRECTUM_ErrorExport.log"
  // Папка для исходящих xml-файлов
  PathOutput = "C:\Directum\Out\"
  FileName = "test.xml"
  
  // ----------------- Начало обмена с порталом по FTP протоколу -----------------

  // Создадим объект ChilkatFTP для обмена по FTP протоколу
  FreeException()
  ExceptionsOff()
  Ftp = CreateObject("ChilkatFTP.ChilkatFTP")
  ExceptionsOn()
                                                                               
  // Если при создании объекта была ошибка
  if ExceptionExists() 
    Error = GetLastException()
    // Ошибка при создании объекта ChilkatFTP. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Ошибка при создании объекта ChilkatFTP. Подробнее: "&Error.Message)))      
    FreeException()
    Прервать()
  endif 

  // Адрес портала  
  Ftp.Hostname = PortalHostName
  // Логин  
  Ftp.Username = PortalUserName
  // Пароль  
  Ftp.Password = PortalPassword
  // Порт  
  Ftp.Port = PortalPort
  // Пассивный режим обмена  
  Ftp.Passive = 1                

  // Соединимся с FTP-сервером портала
  Success = Ftp.Connect()
  // Если соединиться не удалось
  if (Success <> 1)
    // Ошибка соединения с FTP-сервером портала. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Ошибка соединения с FTP-сервером портала. Подробнее: "&Ftp.LastErrorText)))      
    Прервать()
  endIf
  
  // Перейдем в корневой каталог 
  Success = Ftp.ChangeRemoteDir(PortalRootDir)
  // Если перейти не удалось
  if (Success <> 1)
    // Не удалось перейти в корневой каталог. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Не удалось перейти в корневой каталог. Подробнее: "&Ftp.LastErrorText)))      
    Прервать()
  endif
  
  // Выгрузка ответного xml-файла по FTP-протоколу на портал
  Success = Ftp.PutFile(PathOutput&FileName; FileName)
  // Если выгрузить не удалось
  if (Success <> 1)
    // Не удалось выгрузить ответный xml-файл на портал. Подробнее:  
    ФайлЗаписать(LogFileName; 'Д'; Format(MsgTemplate;
                ArrayOf(CR; TAB; Today(); Time(); 'ChilkatFTP'; 
                "Не удалось выгрузить ответный xml-файл на портал. Подробнее: "&Ftp.LastErrorText)))      
    Прервать()
  endif
  Ftp.Disconnect

// ----------------- Конец обмена с порталом по FTP протоколу  -----------------

Если возможностей данной бесплатной компоненты недостаточно, то у неё есть платный вариант Chilkat FTP2 с расширенным функционалом. Скачать её можно по той же ссылке, что и Chilkat FTP на странице загрузки проекта или по прямой ссылке Chilkat FTP2.

Возможности DIRECTUM можно также расширить другими ActiveX-компонентами этого разработчика. Ознакомиться с их списком можно по ссылке Chilkat ActiveX Components Documentation. Свободно распространяемые компоненты для коммерческого и некоммерческого использования отмечены символом (F).

Документация: ChilkatFtp ActiveX Reference (Visual Basic).zip (4,49 Кб)

COM-сервер: FtpActiveX.msi (648,50 Кб)

8
Авторизуйтесь, чтобы оценить материал.
1
Вячеслав Смирнов

Сам по себе FTP является старейшим протоколом передачи файлов и в современных условиях использовать его в чистом виде нужно с осторожностью. Сам процесс передачи файлов в пассивном режиме не особо надёжен: достаточно угадать порт, открытый FTP сервером, чтобы перехватить соединение (в накоторых FTP серверах порты выдаются последовательно, так что подобрать порт "соседнего" соединения вполне возможно). А также поток данных не защищен в процессе передачи (не используется ни шифрование и подпись пакетов).

Т.е. не нужно забывать о безопаности, передавая по сети данные, которые попадут как в систему DIRECTUM так и на портал. Если обложить передаваемые файлы цифровой подписью (если раскрытия данных мы не боимся - всё равно они попадут на портал, и достаточно того, что их не подделают) и/или передавать их в зашифрованном виде (если боимся раскрытия данных), то тогда вариант интеграции с порталами по протоколу FTP можно использвать без опаски.

Дмитрий Тарасов

Согласен, просто доступ к порталу был только по FTP, а пассивный режим обмена указал для примера :)

Вячеслав Смирнов

Никаких замечаний к статье не имею )) то что доступ только по FTP я понял. А для безопасности можно воспользоваться имеющимися в ISBL средствами шифрования, в частности интерфейсом IEncrypter – шифратор данных (описание есть в документации: Справочная система/Объектная модель DIRECTUM/Объекты DIRECTUM/Криптография). Нужно только будет найти способ рассшифровки этих данных на стороне портала (никогда не работал с шифрованием).

А по воводу пассивного режима - он только и применяется. Активный редко используется. Ведь при активном нужно на стороне клиента открывать новые порты для соединения, т.е. и использование прокси-серверов и правил брандмауэров (не знаю как правильно пишется) препятствуют использованию активного режима.

Как правило, система DIRECTUM находится за DMZ и любые контакты с внешним миром (порталом) проходят через прокси-сервер, который обложен различными сканерами и фильтрами, а все прочие порты закрыты наглухо. И открывай/не открывай - брандрауэр заблокирует их всё-равно.

Дмитрий Тарасов

Про шифрование я как-то даже и не подумал к сожалению. Надо будет как-нибудь попробовать.

По поводу пассивного режима и брандмауэров, действительно, все так и было. Открыли только требуемые для обмена порты и через них и работали.

Авторизуйтесь, чтобы написать комментарий