| 
 
  
	| Работа с файлами на стороне клиента 
 
 |  
	
		| Предыдущая тема :: Следующая тема |  
		| Автор | Сообщение |  
		| Wazuuuuup Участник
 
 
 Вступление в Клуб: 03.03.2014
 
 | 
			
				|  Пн Мар 03, 2014 15:56   Работа с файлами на стороне клиента |   |  
				| Полезность: Нет оценки 
 |  
				| Всем здравствуйте! Появилась необходимость создать механизм репликации файлов шаблонов отчетов на рабочие места пользователей.
 Вкратце, суть сводится к справочнику с записями о каждом шаблоне на сервере с версией и проверке актуальности версии шаблона у клиента.
 Смотрим версию шаблона в справочнике, смотрим версию у клиента в каталоге(допустим в тхт файлике список всех шаблонов и их версии), и в случае если у клиента шаблон устарел(или отсутствует), то заменяем(копируем) шаблон клиенту с сервера.
 
 Столкнулся с проблемой, что функция stdio.open ни в какую не хочет открывать файлы на клиенте, только на сервере.
 Знаю, что есть "Экспорт-импорт файлов" FILE$LOAD, который по идее должен решить мою проблему, но никак не могу разобраться как его применять..
 Не могли бы вы подсказать как его использовать? Или какое-нибудь другое решение
 |  |  
		|  |  
		| dbmaslov Профи
 
 
 Вступление в Клуб: 11.07.2007
 
 | 
			
				|  Пн Мар 03, 2014 17:30    |   |  
				| Полезность: Нет оценки 
 |  
				| Добрый день, коллега! 
 Добро пожаловать в Клуб.
 
 Разработка интересная. Вам поможет исследование операций работающих с файлами. Таких много. К сожалению сейчас нет под рукой словаря данных. Посмотрите через поиск в текстах операций словосочетание stdio.open.
 
 У меня встречные вопросы:
 1. как вы будете сверять файлы? не уверен, что используемый механизм в ЦФТ даст вам много информации о файле (максимум размер, а дату модификации скорее всего не получить).
 
 2. не проще ли все шаблоны держать на централизованном сетевом диске и централизованно их обновлять?
 |  |  
		|  |  
		| Random Эксперт
 
 
 Вступление в Клуб: 27.06.2011
 
 | 
			
				|  Вт Мар 04, 2014 05:30   Re: Работа с файлами на стороне клиента |   |  
				| Полезность: 1 
 |  
				|  	  | Wazuuuuup пишет: |  	  | Всем здравствуйте! Появилась необходимость создать механизм репликации файлов шаблонов отчетов на рабочие места пользователей.
 Вкратце, суть сводится к справочнику с записями о каждом шаблоне на сервере с версией и проверке актуальности версии шаблона у клиента.
 Смотрим версию шаблона в справочнике, смотрим версию у клиента в каталоге(допустим в тхт файлике список всех шаблонов и их версии), и в случае если у клиента шаблон устарел(или отсутствует), то заменяем(копируем) шаблон клиенту с сервера.
 
 Столкнулся с проблемой, что функция stdio.open ни в какую не хочет открывать файлы на клиенте, только на сервере.
 Знаю, что есть "Экспорт-импорт файлов" FILE$LOAD, который по идее должен решить мою проблему, но никак не могу разобраться как его применять..
 Не могли бы вы подсказать как его использовать? Или какое-нибудь другое решение
 | 
 
 Прежде чем заниматься разработкой, необходимо вникнуть в парадигму клиент-сервер.
 А для ТЯ2 - так и в парадигму трёхзвенной архитектуры. Но о ней в другой раз.
 
 Итак, представьте себе двух друзей, одного назовём Клерк, и он выполняет инструкции, составленные на VBS, другого назовём СЕРВЕР, и он выполняет инструкции, составленные на PL+ (pl/sql).
 
 Общаться они могут посредством телефона, это не очень медленно, но и не особенно быстро.
 Сервер находится в помещении архива банка, с огромной картотекой. Он практически всемогущ. Однако, чтобы злые люди не заставили его выполнять злые дела, помещение архива банка закрыто на 70 замков, приставлена охрана, и просто так на улицу погулять не выйдешь.
 
 Клерков много. Каждый Клерк находится в своём офисе и общается с миром через окошко приёма-выдачи документов. Подойдёт человек, поговорит, и уйдёт. И телефон ещё выключит.
 
 Сервер сам обзванивать офисы не может.
 
 И вот вы заставляете сервер сбегать в офис, оставить там документы? Первый же вопрос - а в какой? А если он закрыт? И т.д.
 
 Или наоборот, сбегать в офис, забрать документы.
 
 Максимум, вы можете дождаться, когда нужный клерк позвонит и спросит: а мои документы готовы? Тогда Сервер продиктует инструкции по телефону, клерк их выполнить и передаст клиенту.
 
 Ну или наоборот, Клерк продиктует документы Серверу.
 
 Делается это по определённому протоколу.
 
 Последний раз редактировалось: Random (Вт Мар 04, 2014 05:49), всего редактировалось 1 раз
 |  |  
		|  |  
		| Random Эксперт
 
 
 Вступление в Клуб: 27.06.2011
 
 | 
			
				|  Вт Мар 04, 2014 05:44   Re: Работа с файлами на стороне клиента |   |  
				| Полезность: 1 
 |  
				| Итак, процессы сервер-клиент работают следующим образом: 1. на закладке доп.свойств есть рамка "Проверки". В ней два значения - "при загрузке операции" и "при смене элемента управления".
 Проследите, чтобы были Клиент/Сервер.
 
 2. если вы будете работать с элементом FILE$LOAD, вам придётся дожидаться обработки тела операции, потому что копирование файла произойдёт после нажатия кнопки OK, но до выполнения тела операции.
 
 3. поэтому проще в секции валидации вызвать операцию, которая занимается копированием файлов. Например, DOCUMENT.COPYFILES. Поищите примеры, их много.
 
 4. Это получается примерно так:
 а) вы предлагаете пользователю выбрать файл.
 б) вы предлагаете по окончании выбора нажать кнопку "принять".
 в) по нажатии кнопки обрабатываете VB-событие OnClick, посылаете на сервер событие валидации с параметром - имя файла. Это событие отсылается немедленно, обрабатывается и управление возвращается только после его завершения.
 г) на сервере вы получаете имя файла, заполняете нужные переменные, выполняете запуск операции копирования. Сразу предупреждаю, операция копирования должна выполниться в АРМ Навигатор, то есть на клиенте, а значит, вы можете только поджечь бикфордов шнур и всё. Когда вы вернёте управление в VB (выйдете из секции валидации), а затем выйдете и из события OnClick, только тогда АРМ Навигатор запустит операцию копирования файла.
 д) после этого пользователь должен нажать ещё кнопку "Обработать принятый файл". Ну, тут уже файл будет на сервере, обрабатывайте.
 
 
 А то ещё есть способы читать файлы из VB...
 |  |  
		|  |  
		| Random Эксперт
 
 
 Вступление в Клуб: 27.06.2011
 
 | 
			
				|  Вт Мар 04, 2014 06:04   Re: Работа с файлами на стороне клиента |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | Wazuuuuup пишет: |  	  | Всем здравствуйте! Появилась необходимость создать механизм репликации файлов шаблонов отчетов на рабочие места пользователей.
 | 
 Что касается самой задачи.
 Вам не кажется, что обновлять шаблоны только для того, чтобы они были верной версии - это несколько бессмысленное занятие?
 
 Может быть, всё-таки обновлять шаблон в тот момент, когда он нужен?
 Когда есть реальная потребность с конкретным клиентом, конкретными данными, конкретным шаблоном?
 
 Зачем ронять деревья в лесу, когда там никого нет
  |  |  
		|  |  
		| Wazuuuuup Участник
 
 
 Вступление в Клуб: 03.03.2014
 
 | 
			
				|  Вт Мар 04, 2014 08:52    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | dbmaslov пишет: |  	  | Добрый день, коллега! 
 Добро пожаловать в Клуб.
 
 Разработка интересная. Вам поможет исследование операций работающих с файлами. Таких много. К сожалению сейчас нет под рукой словаря данных. Посмотрите через поиск в текстах операций словосочетание stdio.open.
 
 У меня встречные вопросы:
 1. как вы будете сверять файлы? не уверен, что используемый механизм в ЦФТ даст вам много информации о файле (максимум размер, а дату модификации скорее всего не получить).
 
 2. не проще ли все шаблоны держать на централизованном сетевом диске и централизованно их обновлять?
 | 
 
 
 
  	  | Random пишет: |  	  | Что касается самой задачи. Вам не кажется, что обновлять шаблоны только для того, чтобы они были верной версии - это несколько бессмысленное занятие?
 
 Может быть, всё-таки обновлять шаблон в тот момент, когда он нужен?
 Когда есть реальная потребность с конкретным клиентом, конкретными данными, конкретным шаблоном?
 
 Зачем ронять деревья в лесу, когда там никого нет Smile
 | 
 
 Коллеги, спасибо за ответы!
 По поводу ваших вопросов:
 1. Актуализация и хранение шаблона необходимы для устранения затрат на постоянное подтягивание шаблонов с сервера. Сами шаблоны у нас модифицируются крайне редко, поэтому затраты на актуализацию будут меньше, чем на постоянное скачивание.  И самое главное, это требование безопасности - избавиться от централизованного хранилища на сервере, на которое будут все ломиться.
 2. Сама актуализация будет происходить по такой схеме: изначально создается справочник с записями по каждому шаблону вида:
 
 Код шаблона
Версия
 Каталог шаблона у пользователя
 Каталог шаблона на сервере
 Наименование файла шаблона
 
 У пользователя шаблоны будут хранится локально в определенной папке вместе с файлом версий шаблонов. В этом файле построчно хранятся записи типа "Код шаблона - версия шаблона".
 
 Актуализация будет происходить в момент вызова операции выполнения отчета.
 Сравнение будет происходить путем сравнения версии из справочника и версии из файла на клиенте. Думаю еще добавить сравнение размеров файла.
 
 Проблема в том, что я думал уместить все в одну библиотеку, а в библиотеках, как известно, нет ни проверки ни клиент-скрипта... Видимо придется писать отдельную операцию.
 
 По поводу того, что придется дожидаться тела операции: у нас отчеты вынесены в отдельный справочник(он потом выносится в отдельный пункт меню навигатора), при этом часть отчетов расположены в других местах и вызываются они через PLPCALL. Есть вариант создать для остальных отчетов такие же операции, и в них перед вызовом производить актуализацию, но очень хотелось бы избежать этого...
 |  |  
		|  |  
		| Alexsey Эксперт
 
 
 Вступление в Клуб: 06.09.2007
 
 | 
			
				|  Вт Мар 04, 2014 10:23    |   |  
				| Полезность: Нет оценки 
 |  
				| А что мешает собрать строку для запуска операции динамически? Например сделали несколько операций, это ладно. А далее строку для запуска собираете какой-либо функцией какой-нибудь библиотеки строку для запуска и запускаете ее в клиент-скрипте, он как раз может дождаться выполнения операции и далее дернуть необходимый функционал. В результате получите единую точку вызова
 
 Как раз получится то, что писал Ramdom. Вы говорите клерку позвонить серверу и подождать его ответа, в зависимости от ответа выполнить следующие действия.
 _________________
 всегда есть как минимум 2 выхода
 |  |  
		|  |  
		| Wazuuuuup Участник
 
 
 Вступление в Клуб: 03.03.2014
 
 | 
			
				|  Вт Мар 04, 2014 13:26    |   |  
				| Полезность: Нет оценки 
 |  
				| Сразу извиняюсь - теги чего-то не тянутся =\ 
  	  | Admin пишет: |  	  | В примерах кода не пишите слово CODE в квадратных скобках и все получится. Я исправил | 
 
 Решил сделать все в одной операции, в которую достаточно передать код шаблона.
 
 Уткнулся в ту же самую проблему с отказом открытия файла =\
 Установил проверки на Клиент,Сервер. Создал параметр типа FILE$LOAD и параметр для приема кода шаблона.
 
 Проверка:
 
  	  | Код: |  	  | begin
 if p_message = 'DEFAULT' then
 
 P_TEMPLATE_CODE := 'GA_PRN_OTN';
 P_FILE_CHECK.[SRC_TYPE]   := false;
 P_FILE_CHECK.[DST_TYPE]   := true;
 P_FILE_CHECK.[DST_DELETE]   := true;
 
 P_FILE_CHECK.[SRC_PATH] := ::[GA_TEMPLATE_REPL](CODE = P_TEMPLATE_CODE).[CLIENT_PATH];
 vTemplateFileName := ::[GA_TEMPLATE_REPL](CODE = P_TEMPLATE_CODE).[TEMPLATE_FILE];
 P_FILE_CHECK.[SRC_NAME] := replace(vTemplateFileName,'.xlt','_version.txt');
 
 P_FILE_CHECK.[DST_PATH] := [SYSTEM_PARAMS]::[GET]('PATH',null);
 P_FILE_CHECK.[DST_NAME]:=P_FILE_CHECK.[SRC_NAME]||'_'||utils.session_id;
 
 elsif p_message = 'VALIDATE' then
 null;
 end if;
 end;
 
 | 
 
 И в теле:
 
  	  | Код: |  	  | begin
 vFile := stdio.open(P_FILE_CHECK.[DST_PATH],P_FILE_CHECK.[DST_NAME],'r');
 dbms_output.put_line('vFile := '||vFile);
 stdio.close(vFile);
 end;
 
 | 
 
 Файл на клиенте лежит в каталоге C:\123\ с именем файла GA_PRN_OTN_version.txt
 При попытке выполнения падает с ошибкой "[./GA_PRN_OTN_version.txt_000A85650001] Файл не найден"
 |  |  
		|  |  
		| Random Эксперт
 
 
 Вступление в Клуб: 27.06.2011
 
 | 
			
				|  Ср Мар 05, 2014 05:40    |   |  
				| Полезность: 1 
 |  
				|  	  | Wazuuuuup пишет: |  	  | Сразу извиняюсь - теги чего-то не тянутся =\ 
  	  | Admin пишет: |  	  | В примерах кода не пишите слово CODE в квадратных скобках и все получится. Я исправил | 
 
 Решил сделать все в одной операции, в которую достаточно передать код шаблона.
 Файл на клиенте лежит в каталоге C:\123\ с именем файла GA_PRN_OTN_version.txt
 При попытке выполнения падает с ошибкой "[./GA_PRN_OTN_version.txt_000A85650001] Файл не найден"
 | 
 
 Что-то не понимаю я, как это - достаточно передать параметр.
 Выполняете вы операцию как? просто вызовом типа ::[ТРА-Та-Та].RECEIVE_FILE(p_file) ? Если так, то как раз вы пытаетесь сервер заставить сбегать в офис, даже не сообщяя ему об адресе офиса.
 Ещё раз - для выполнения копирования файла НЕОБХОДИМО поднятие экранной формы операции.
 Поднятие ЭФ происходит только с помощью АРМ Навигатор.
 Это означает, что вы не можете копировать файлы с клиента на сервер, например, в операциях, исполняемых с помощью Oracle Jobs, как минимум - с помощью синтаксиса plp-call
 
 Удобнее всего не работать с FILE$LOAD напрямую, этот контрол не особенно гибок.
 Я повторю ещё раз - копирование файла осуществляется МЕЖДУ обработкой секции валидации и секции тела. То есть когда вы нажимаете кнопку OK, то, если у кнопки установлен признак CheckValidate, сначала будет обработана секция валидации, и лишь затем копирование файла, и потом - тело операции.
 
 А прямым вызовом операции в теле другой операции вы переходите сразу к телу этой операции. Короче, это сложно, не грейте голову.
 
 Удобнее всего работать с операциями, запускаемыми через вывод в буфер сессии.
 
 Если привести аналогию, то вы отправляете клерку письмо с просьбой доставить вам файл. Однако вы не можете сразу после отправки письма бежать в почтовый ящик и работать с файлом, его там ещё нет.
 
 Ведь на самом деле вы ничего не копируете. Вы выводите в буфер сессии некую строчку, которая сама по себе ничего не значит. АРМ Навигатор имеет соединение с сервером. В момент какого-либо события АРМ обрабатывает VB-скрипт у контрола, если он есть, потом в зависимости от установок доп.свойств - функцию Main в VBS или секцию валидации на сервере.
 Просто касательно буфера сессии есть некие договорённости - после того, как вызов операции с сервера завершится, прочитать буфер сессии, разобрать и если синтаксис похож на синтаксис PLPCALL, попытаться разобраться в строчке и запустить операцию.
 Именно об этом я говорил, когда писал о бикфордовом шнуре пару сообщений назад.
 Управление не вернётся в АРМ Навигатор, точнее, АРМ Навигатор не будет разбирать буфер сессии, пока не отработает вся операция на сервере( вся секция валидации ) или вся функция VBS.
 
 Итак, вот операция:
 Групповая;
 доп.свойства: выводит команды в буфер сессии
 При загрузке: Сервер, Клиент;
 При смене - Клиент, Сервер.
 
 На ЭФ: текстовое поле для ввода пути файла на клиенте (у клерка), связанное с переменной V_FILE, в VBS известное как T_FILE.
 Кнопка "Поехали", в VBS известная как B_GO; у кнопки установлен признак CheckValidate.
 Кнопка "Проверить", в VBS известная как B_CHECK; у кнопки установлен признак CheckValidate.
 
 VBS:
  	  | Код: |  	  | Public Function Main(LastControl)
 Main = true
 ' функция должна быть, но не обязана выполнять что-либо
 End Function
 
 sub B_GO_OnClick
 Form1.ScriptServerValidate OK, "SERVER_LOAD"
 end sub
 
 sub B_CHECK_OnClick
 Form1.ScriptServerValidate OK, "SERVER_CHECK"
 end sub
 
 | 
 
 Секция валидации:
 
  	  | Код: |  	  | pragma macro(CPFC, 'REPS_DATA.COPYFILES');-- также есть такие операции в REPS, RUNTIME и, кажется, в DOCUMENT
 pragma macro(CPFS, 'REPS_DATA COPYFILES');
 
 var vPath varchar2(32767);
 var vFilename varchar2(32767);
 
 if p_message = 'VALIDATE' and p_info = 'SERVER_LOAD' then
 vPath := substr(v_file, 1, instr(v_file, '\', -1)-1);   -- путь до каталога с файлом
 vFilename := substr(v_file, instr(v_file, '\', -1)+1);   -- имя файла
 
 &CPFC.idx := nvl(&CPFC.tbl_F$L.last,0);
 -- client
 &CPFC.tbl_F$L(&CPFC.idx+1).[SRC_NAME]      := vFilename;
 &CPFC.tbl_F$L(&CPFC.idx+1).[SRC_PATH]      := vPath;
 &CPFC.tbl_F$L(&CPFC.idx+1).[SRC_TYPE]      := false;
 &CPFC.tbl_F$L(&CPFC.idx+1).[SRC_DELETE]   := false;
 -- server
 &CPFC.tbl_F$L(&CPFC.idx+1).[DST_NAME]      := vFilename;
 &CPFC.tbl_F$L(&CPFC.idx+1).[DST_PATH]      := '.'; -- это путь на сервере, файл будет доступен через ./file_name
 &CPFC.tbl_F$L(&CPFC.idx+1).[DST_TYPE]      := true;
 &CPFC.tbl_F$L(&CPFC.idx+1).[DST_DELETE]   := false;
 
 &CPFC.idx := 0;
 stdio.put_line_buf('<% CALL '||&CPFS||' ' || nvl(::[SYSTEM]%id, 1) || ' %>');
 
 elsif    p_message = 'VALIDATE' and p_info = 'SERVER_CHECK' then
 vFilename := substr(v_file, instr(v_file, '\', -1)+1);   -- имя файла
 if ::[REPS_DATA].[LIB_FILE].FileExists('./'||vFilename) then -- не хочу приводить реализацию функции, глянь сам
 debug_pipe('Ура-ура!',0);
 else
 debug_pipe('Эх... что-то пошло не так...',0);
 end if;
 end if;
 
 | 
 |  |  
		|  |  
		| Wazuuuuup Участник
 
 
 Вступление в Клуб: 03.03.2014
 
 | 
			
				|  Ср Мар 05, 2014 09:20    |   |  
				| Полезность: Нет оценки 
 |  
				| Спасибо за развернутый ответ, теперь понятно. 
  	  | Random пишет: |  	  |  	  | Wazuuuuup пишет: |  	  | Сразу извиняюсь - теги чего-то не тянутся =\ 
  	  | Admin пишет: |  	  | В примерах кода не пишите слово CODE в квадратных скобках и все получится. Я исправил | 
 
 Решил сделать все в одной операции, в которую достаточно передать код шаблона.
 Файл на клиенте лежит в каталоге C:\123\ с именем файла GA_PRN_OTN_version.txt
 При попытке выполнения падает с ошибкой "[./GA_PRN_OTN_version.txt_000A85650001] Файл не найден"
 | 
 
 Что-то не понимаю я, как это - достаточно передать параметр.
 | 
 Я имел ввиду, что в пользователь вводит только код шаблона, имена файлов вводятся в коде.
 
 
  	  | Random пишет: |  	  | Выполняете вы операцию как? просто вызовом типа ::[ТРА-Та-Та].RECEIVE_FILE(p_file) ? Если так, то как раз вы пытаетесь сервер заставить сбегать в офис, даже не сообщяя ему об адресе офиса. | 
 Операцию выполняю через навигатор. Но потом планировал так и сделать, спасибо что предупредили)
 
 Но проблемы это не отменяет - операция, которую я описал в предыдущем посте, так и не работает. Может проблема в том, что я сам контрол FILE_$LOAD не вынес на форму? На форме у меня только текстовое поле для ввода кода шаблона.
 |  |  
		|  |  
		|  |  
  
	| 
 
 | Вы не можете начинать темы Вы не можете отвечать на сообщения
 Вы не можете редактировать свои сообщения
 Вы не можете удалять свои сообщения
 Вы не можете голосовать в опросах
 
 |  |