В первой части мы разобрались, почему сервер 1С «слеп» к файлам на вашем диске C: , и подготовили поле ввода для пути к файлу. Пользователь нажал на заветные три точки ... и выбрал документ. Путь к файлу мы научились делать за 3 шага. Что дальше? Теперь нам нужна большая, красивая кнопка, которая заставит этот файл оторваться от вашего компьютера, улететь на сервер, превратиться там в данные базы и вернуть нам красивое окошко с сообщением. Давайте по шагам разберем, как спроектировать это и запустить клиент-серверный мост.

Шаг 4. Создаем кнопку действия «Выполнить загрузку». Просто нарисовать кнопку на экране мало — нужно объяснить платформе, что должно произойти при клике.

В редакторе формы нашей внешней обработки переходим на вкладку Команды (она находится в правом верхнем окне, прямо рядом с «Реквизитами»). Нажимаем зелёный плюс «Добавить» и называем нашу команду просто и понятно: Загрузить. Берем эту команду мышкой и перетаскиваем в левое верхнее окно Элементы, прямо под наше поле с путем к файлу.

На форме появится кнопка. Выделите её, откройте свойства (Alt + Enter) и в поле Заголовок укажите текст, который увидит пользователь: Загрузить.

Шаг 5. Выбор типа обработчика события. Теперь необходимо связать созданную команду с программным кодом. В свойствах команды найдите строку Действие и нажмите на пиктограмму с лупой. Платформа откроет диалоговое окно выбора. Из предложенного списка необходимо выбрать пункт: «Создать на клиенте и процедуру на сервере без контекста».

Давайте разберем, почему платформа предлагает разделение и почему выбор директивы «без контекста» (&НаСервереБезКонтекста) является наиболее правильным.

Почему процедура создается и на клиенте, и на сервере?

Нажатие кнопки пользователем — это действие, которое физически происходит в интерфейсе программы, то есть на Клиенте. Однако клиентская процедура не имеет прямого доступа к серверным вычислениям и механизмам базы данных. Для этого управление необходимо передать на Сервер. Данный тип обработчика автоматически создает пару связанных процедур, обеспечивая правильную передачу данных между уровнями архитектуры.

 В чем разница между «на сервере» и «на сервере без контекста»?

Когда вызывается обычная процедура &НаСервере, платформа 1С берет со стороны клиента абсолютно все данные формы (все реквизиты, таблицы, элементы интерфейса), упаковывает их и пересылает на сервер. Сервер тратит время и память на обработку этого объема информации, а затем отправляет всё обратно на клиент. Это называется «передачей контекста формы».

Если выбрать &НаСервереБезКонтекста:Платформа выполняет «легкий» вызов. Сервер получает только те переменные, которые мы сами явно передадим ему в параметрах. Контекст формы (интерфейс, лишние реквизиты) остается нетронутым на клиенте. Скорость выполнения операции возрастает в разы, так как программе не приходится гонять лишние мегабайты данных по сети между клиентом и сервером. Сервер получит только те переменные, которые передадим ему в параметрах (в нашем случае — файл). Сама форма и её элементы останутся на клиенте, не нагружая сеть и память сервера лишней работой. Поэтому использование директивы БезКонтекста — это стандарт качественной и производительной разработки в 1С. Нажимаем«ОК» платформа сгенерирует в модуле формы шаблоны двух процедур, готовых к написанию алгоритма.

После того как платформа создала пару процедур (клиентскую и бесконтекстную серверную), у начинающих разработчиков часто возникает вопрос: «Мы же создали серверную процедуру, почему мы не можем сразу передать туда строку с путем к файлу и начать его читать?»

Нет, сразу написать туда весь код чтения файла нельзя. И в этом кроется главная архитектурная ловушка для новичков. Когда платформа генерирует пустой шаблон процедуры &НаСервереБезКонтекста, может возникнуть соблазн сразу прописать туда привычный код (например, ТабДок.Прочитать(ПутьКФайлу)). Но программа мгновенно выдаст ошибку.

Причина кроется в строгих правилах безопасности и изоляции уровней архитектуры 1С.

Сервер не имеет доступа к вашему диску: Ваша серверная процедура выполняется в сеансе операционной системы на сервере приложений 1С. Если передадим на сервер обычную строку C:\Users\Nina\Desktop\Лист Microsoft Excel.xlsx, сервер попытается найти этот файл на своем собственном жестком диске (там, где физически установлена серверная часть 1С), а не на вашем персональном компьютере. Естественно, он выдаст ошибку «Файл не найден». Бесконтекстный вызов изолирован от формы: Поскольку мы выбрали директиву БезКонтекста, серверная процедура не видит саму форму нашей обработки. Она не может напрямую «посмотреть» в реквизит ПутьКФайлу на экране. Она видит только то, что мы передадим ей «в руках» через параметры. Именно поэтому мы не можем сразу приступить к разбору данных на сервере.

 Шаг 6. Прежде чем написать код нужно понять еще один нюанс. В современных версиях платформы 1С (начиная с 8.3.15) старая и привычная функция ПоместитьФайлВоВременноеХранилище() признана устаревшей. Браузеры и операционные системы больше не разрешают программам «намертво» замораживать интерфейс пользователя, пока тяжелый файл летит по сети на сервер. Платформа требует, чтобы загрузка происходила в асинхронном режиме. Это значит, что файл отправляется в фоне, а программа ждет специального сигнала о том, что передача завершена.

Именно из-за этого современного правила безопасности наш мост усложняется: к стандартной паре процедур (на клиенте и на сервере без контекста) добавляется третье промежуточное звено — процедура обратного вызова (или завершения).

Теперь мост в клиент-серверной архитектуре и управляемых формах выглядит так:

1. Процедура на клиенте запускает фоновую отправку файла и говорит системе: «Как только файл долетит до сервера, автоматически передай управление процедуре завершения». И сама сразу закрывается.

2. Процедура завершения на клиенте встречает текстовый документ (ссылку) и передает его дальше. Процедура завершения ничего на сервер не записывает. Сам файл в эту строку записывает встроенная функция платформы. Например, в коде этот адрес выглядит как текстовая строка: e1cib/tempstorage/89a557bb-6927-4bda —  документ по сети еще раз передавать не нужно, сервер найдет его в памяти именно по этому идентификатору.

Как сервер подхватывает эту строку?

Сама по себе серверная функция не узнает о появлении файла в памяти. Поэтому наша процедура завершения делает ключевой шаг: она вызывает бесконтекстную функцию сервера и передает полученную адресную строку в качестве параметра — ЗагрузитьДанныеНаСервере(РезультатПомещения.Адрес).

3. Функция на сервере без контекста по временному адресу сохраняет файл к себе на сервер с созданным адресом, выполняет ту обработку, которую мы пропишем в коде, и возвращает на клиент ровно то сообщение, которое мы написали.

Шаг 7. Теперь, когда логика клиент-серверного моста понятна, реализуем её в коде .  Скопируйте и вставьте этот код:

&НаСервереБезКонтекста
Функция ЗагрузитьДанныеНаСервере(Знач АдресХранилища)
	
	// 1. Сервер по полученному трек-номеру (адресной строке) находит файл в памяти
	ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранилища);
	
	// 2. Выполняет ту обработку, которую мы пропишем в коде:
	
	// Создаем на диске сервера пустой файл с расширением xlsx
	ИмяВременногоФайлаСервер = ПолучитьИмяВременногоФайла("xlsx");
	
	// Записываем бинарное содержимое «письма» в этот файл
	ДвоичныеДанныеФайла.Записать(ИмяВременногоФайлаСервер);
	
	// Инициализируем табличный документ 1С для парсинга ячеек Excel
	ТабличныйДокумент = Новый ТабличныйДокумент;
	
	Попытка
		// Сервер считывает внутреннюю структуру Excel-файла
		ТабличныйДокумент.Прочитать(ИмяВременногоФайлаСервер, СпособЧтенияЗначенийТабличногоДокумента.Текст);
		
		// [Именно здесь, ниже этой строки, пишется цикл перебора строк:
		// Для НомерСтроки = 1 По ТабличныйДокумент.ВысотаТаблицы Цикл ...]
		
		ТекстОтвета = "Файл успешно сохранен на сервере";
		
	Исключение
	// ИСПРАВЛЕНО: Используем стандартный метод платформы ПодробноеПредставлениеОшибки
	ТекстОтвета = "Ошибка обработки файла: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;


	// Обязательно удаляем за собой временный файл с диска сервера, чтобы не засорять память
	УдалитьФайлы(ИмяВременногоФайлаСервер);
	
	// 3. Возвращаем результат обработки на Клиент
	Возврат ТекстОтвета;
	
КонецФункции


 
 


&НаКлиенте
Процедура ВыполнитьЗагрузку(Команда)
	
	Если ПустаяСтрока(ПутьКФайлу) Тогда
		ПоказатьПредупреждение(, "Пожалуйста, выберите файл Excel или MXL для загрузки!");
		Возврат;
	КонецЕсли;
	
	Сообщить("--- Запуск умного импорта файла ---");
	
	// Передаем параметры напрямую в метод, убрав лишнее объявление типа
	ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьЗагрузкуЗавершение", ЭтотОбъект);
	
	НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , , ПутьКФайлу, УникальныйИдентификатор);

КонецПроцедуры







&НаКлиенте
Процедура ВыполнитьЗагрузкуЗавершение(РезультатПомещения, ДополнительныеПараметры) Экспорт

	// ИСПРАВЛЕНО: Убрали несуществующее свойство ХранениеВыполнено
	Если РезультатПомещения = Неопределено Тогда
		ПоказатьПредупреждение(, "Ошибка при передаче файла на сервер или операция отменена!");
		Возврат;
	КонецЕсли;
	
	// Передаем серверу чистую адресную строку
	ТекстСообщения = ЗагрузитьДанныеНаСервере(РезультатПомещения.Адрес);
	
	// Выводим пользователю ровно то сообщение, которое вернул сервер
	ПоказатьПредупреждение(, ТекстСообщения);

КонецПроцедуры

Шаг 8. Тестируем готовую форму в режиме «1С:Предприятие»

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

Сохраните ваш файл (Файл — Сохранить как...) на рабочий стол. Он запишется в формате .epf.

Запустите вашу базу 1С в обычном пользовательском режиме (1С:Предприятие).

Нажмите Главное меню — Файл — Открыть и выберите ваш сохраненный файл с рабочего стола и нажмите на созданную кнопку действия «Выполнить загрузку».

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

​

Комментарии (0)