В данном решении запишем картинку в базу данных сразу же после ее выбора.
Итак, создадим форму элемента справочника Товары. Добавим в форму реквизит АдресКартинки (тип Строка), в котором будет храниться навигационная ссылка на реквизит справочника ДанныеФайлаКартинки. Перетащим реквизит АдресКартинки в дерево элементов формы. Установим свойства элемента: Вид – Поле картинки и ПоложениеЗаголовка – Нет.
Создадим команду формы ЗагрузитьКартинку и поместим ее в командную панель формы. При нажатии этой кнопки будут выполняться выбор файла картинки с диска, запись данных картинки в реквизит справочника ДанныеФайлаКартинки и отображение картинки в форме (рис. 4.61).

Рис. 4.61. Форма элемента справочника «Товары»
Обработчик команды ЗагрузитьКартинку заполним следующим образом (листинг 4.36).
Листинг 4.36. Обработчик команды «Загрузить картинку»
&НаКлиенте
Процедура ЗагрузитьКартинку(Команда)
НачатьПомещениеФайла(Новый ОписаниеОповещения("ЗагрузитьКартинкуЗавершение", ЭтотОбъект), , , Истина , УникальныйИдентификатор);
КонецПроцедуры
Загрузка картинки выполняется с помощью немодального метода НачатьПомещениеФайла(), который мы подробно рассматривали выше на стр. .
В первом параметре этого метода описывается процедура обработки оповещения ЗагрузитьКартинкуЗавершение(), в которой в случае выбора файла картинки пользователем будут выполняться действия по загрузке картинки товара (листинг 4.37).
Листинг 4.37. Обработчик оповещения «ЗагрузитьКартинкуЗавершение»
&НаКлиенте
Процедура ЗагрузитьКартинкуЗавершение(Результат, АдресВХранилище, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Результат Тогда
Файл = Новый Файл(ВыбранноеИмяФайла);
Объект.ИмяФайла = Файл.Имя;
АдресКартинки = АдресВХранилище;
ПоместитьФайлКартинки();
КонецЕсли;
АдресКартинки = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ДанныеФайлаКартинки");
КонецПроцедуры
В процедуру обработки оповещения в параметре АдресВХранилище передается адрес во временном хранилище, по которому был помещен файл картинки. В параметре ВыбранноеИмяФайла передается путь к выбранному файлу.
В случае успешного выбора картинки короткое имя файла сохраняется в реквизите справочника ИмяФайла, и данные файла картинки помещаются во временное хранилище. Адрес данных в этом хранилище сохраняется в реквизите формы АдресКартинки.
Затем в процедуре ПоместитьФайлКартинки() выполняется запись данных картинки в реквизит справочника ДанныеФайлаКартинки. И затем с помощью метода ПолучитьНавигационнуюСсылку() реквизиту АдресКартинки присваивается навигационная ссылка на реквизит ДанныеФайлаКартинки, и картинка отображается в форме. В первом параметре метода ПолучитьНавигационнуюСсылку() передается ссылка на объект Объект.Ссылка, а во втором – имя реквизита.
Контекстную серверную процедуру ПоместитьФайлКартинки() заполним следующим образом (листинг 4.38).
Листинг 4.38. Процедура «ПоместитьФайлКартинки()»
&НаСервере
Процедура ПоместитьФайлКартинки()
ЭлементСправочника = РеквизитФормыВЗначение("Объект");
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресКартинки);
ЭлементСправочника.ДанныеФайлаКартинки = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных());
ЭлементСправочника.Записать();
УдалитьИзВременногоХранилища(АдресКартинки);
ЗначениеВРеквизитФормы(ЭлементСправочника, "Объект");
КонецПроцедуры
Чтобы мы могли записать объект, в этой процедуре значение основного реквизита формы Объект преобразуется в значение объекта – элемента справочника. Затем в переменной ДвоичныеДанные сохраняются данные, полученные из временного хранилища по адресу АдресКартинки. Затем создается объект ХранилищеЗначения, в него помещается значение переменной ДвоичныеДанные, и значение объекта ХранилищеЗначения сохраняется в реквизите справочника ДанныеФайлаКартинки. Затем данные объекта – элемента справочника записываются, временное хранилище очищается, и значение измененного объекта преобразовывается обратно в значение основного реквизита формы.
Теперь осталось обеспечить чтение картинки при чтении данных уже существующего объекта. Для этого создадим обработчик события формы ПриЧтенииНаСервере и заполним его следующим образом (листинг 4.39).
Листинг 4.39. Обработчик события «ПриЧтенииНаСервере»
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
АдресКартинки = ПолучитьНавигационнуюСсылку(ТекущийОбъект.Ссылка, "ДанныеФайлаКартинки");
КонецПроцедуры
ПРИМЕЧАНИЕ
Этот пример можно посмотреть в демонстрационной конфигурации «10 (вар. 1) Запись данных объекта в единой транзакции за один серверный вызов».
Запустим «1С:Предприятие» и откроем форму элемента справочника Товары. Если у товара уже была выбрана картинка, она отразится в форме. Нажмем кнопку Загрузить картинку и изменим картинку товара. Выбранная картинка отобразится в поле картинки товара и будет записана в реквизит объекта ДанныеФайлаКартинки (рис. 4.60).
Таким образом, мы добились нужной функциональности формы, но посмотрим теперь на показатели производительности. В результате из обработчика события нажатия кнопки Загрузить картинку (см. листинг 4.36) будет сделано целых пять вызовов сервера! (рис. 4.62).

Рис. 4.62. Показатели производительности
Для наглядности рассмотрим схему программного взаимодействия клиента и сервера (рис. 4.63).

Рис. 4.63. Схема программного взаимодействия сервера и клиента
Два вызова сервера произойдут при выполнении метода НачатьПомещениеФайла(), и эти вызовы оправданны, так как их делает платформа. Один раз сервер вызывается при исполнении метода НачатьПомещениеФайла(), так как он передает картинку с клиентского компьютера во временное хранилище, а второй вызов происходит, потому что навигационная ссылка, возвращенная этим методом, сразу же помещается в реквизит формы АдресКартинки. Это приводит к тому, что форма обновляется, чтобы отобразить картинку по этой ссылке. Если в вызове метода НачатьПомещениеФайла() вместо АдресКартинки использовать другую произвольную переменную, а не реквизит формы, то произойдет только один серверный вызов.
Один вызов сервера будет сделан при записи картинки объекта при вызове серверной процедуры ПоместитьФайлКартинки(). Этого вызова можно избежать, если не записывать картинку сразу при выборе, а хранить данные картинки во временном хранилище до тех пор, пока объект не записан.
И еще два вызова произойдут при выполнении метода ПолучитьНавигационнуюСсылку(). Этот метод выполняет обращение к серверу при получении ссылки на реквизит. Здесь один серверный вызов происходит при получении навигационной ссылки, а второй – потому что она сразу же присваивается реквизиту формы АдресКартинки. Этих вызовов также можно избежать, если использовать навигационную ссылку на временное хранилище для отображения картинки в форме до тех пор, пока объект не записан.