22 янв. 2013 г.

Кэширование изображений

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

Рассмотрим на примере простой конфигурации, которая содержит справочник "Контрагенты" и подчиненный ему справочник "Файлы контрагентов". Справочник "Файлы контрагентов" содержит реквизит ХранилищеИзображения, тип ХранилищеЗначения. Эти данные мы и будем кэшировать при обращении.

Добавляем форму справочника "Файлы контрагентов", добавляем команду и код:

&НаСервере
Процедура ПрочитатьИзображение()

 ХранилищеИзображения = ПоместитьВоВременноеХранилище(Объект.Ссылка.ХранилищеИзображения.Получить(), УникальныйИдентификатор);

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

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
 
 ПрочитатьИзображение();
 
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьИзображение(Команда)
 
 Режим = РежимДиалогаВыбораФайла.Открытие;
 ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
 ДиалогОткрытияФайла.ПолноеИмяФайла = "";
 Фильтр = "(*.jpg)|*.jpg|(*.png)|*.png";
 ДиалогОткрытияФайла.Фильтр = Фильтр;
 ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
 ДиалогОткрытияФайла.Заголовок = "Выберите файл";
 Если ДиалогОткрытияФайла.Выбрать() Тогда
     МассивФайлов = ДиалогОткрытияФайла.ВыбранныеФайлы;
  Данные = Новый ДвоичныеДанные(МассивФайлов[0]);
  ХранилищеИзображения = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);
  Модифицированность = Истина;
 Иначе
     Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!""";
     Предупреждение(НСтр(Текст));
 КонецЕсли;
 
КонецПроцедуры

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

&НаСервере
Процедура УстановитьОтборФайлов()

 СписокФайлы.Отбор.Элементы[0].ПравоеЗначение = Объект.Ссылка;

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

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
 
 УстановитьОтборФайлов();
 
КонецПроцедуры

&НаСервере
Функция ПолучитьДанныеФайла(СсылкаФайл)

 Возврат СсылкаФайл.ХранилищеИзображения.Получить();

КонецФункции

&НаКлиенте
Процедура СписокФайлыПриАктивизацииСтроки(Элемент)
 
 СсылкаФайл = Элемент.ТекущиеДанные.Ссылка;
 Данные = ПолучитьДанныеФайла(СсылкаФайл);
 ХранилищеИзображения = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);
 
КонецПроцедуры 

В текущей реализации изображения в форму будут загружаться при каждом обращении. Допустим, у нас низкоскоростное соединение/USB-модем. В этом случае объемные изображения будут ощутимо долго подгружаться. А если еще пользователь переключается между ними, то дискомфорт при работе обеспечен. Дописываем код формы, объявляем в модуле переменную для кэширования на стороне клиента:

&НаКлиенте
Перем КэшИзображений;

Инициализируем ее в процедуре ПриОткрытии:

&НаКлиенте
Процедура ПриОткрытии(Отказ)
 
 КэшИзображений = Новый Соответствие;
 
КонецПроцедуры 

И дописываем процедуру СписокФайлыПриАктивизацииСтроки, в кэш помещаем содержимое реквизита ХранилищеИзображения, соответствие происходит по ссылке элемента справочника ФайлыКонтрагентов:

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

2. При повторном обращении изображение уже считывается из кэша:

Таким образом, видим, что время повторного получения из кэша сведено к минимуму.

Скачать конфигурацию

Комментариев нет:

Отправить комментарий