gifts2017

Просмотр изображений через тонкий клиент с жесткого диска сервера UPD

Опубликовал Александр Медведев (anig99) в раздел Программирование - Практика программирования

Загрузка с сервера, автоматическое масштабирование, увеличение-уменьшение, поворот. На примере просмотра фотографии сделанных торговыми агентами через систему приема заявок МОБИ-С. UPD: при вставке кода процедуры УстановитьТекстHTMLСФото не вставился собственно html код, исправил

Встала задача дать возможность офису в другом городе просматривать фотографии сделанные торговыми агентами. Доступ к базе осуществляется через интернет с помощью тонкого клиента.

Система Моби-с загружает фотографии от торговых клиентов и хранит их в папках агентов. Фотографии могут быть привязаны как к товарам, так и к контрагентам. Интересовало именно  фотографии привязанные к контрагентам. Привязка к контрагенту осуществляется через название файла.

Небольшое тестирование показало, что подгружать фотографии сразу в тонкий клиент слишком долго. Поэтому обработка сначала кэширует данные в папке Мои документы на локальном компьютере, куда сохраняет ещё не загруженные фотографии (с отбором по агенту). Кроме того, было выяснено, что предлагаемый 1с способ размещения картинки на форме через декорацию и временное хранилище всё равно прогоняет данные с локального компьютера на сервер. Это опять-таки негативно сказывается на скорости просмотра фотографий. Поэтому в обработке реализован просмотр через html-поле и динамическую генерации кода. Кроме того, разными средставами реализовано:

  • автоматическое масштабирование под размер окна 
  • увеличение-уменьшение изображения
  • поворот изображения
  • открытие в программе для просмотра изображений

Выбор периода осуществляется с помощью публикации Диалог ввода периода, УФ

Собственно процедуры и функции:

Сохранение изображений

&НаКлиенте
Процедура СохранитьФайлыАгента(ТекДанные) //сохраняет фотографии на жесткий диск, ТекДанные - строка дерева значений (динамического списка)
	
	Если ТекДанные = Неопределено Тогда Возврат; КонецЕсли;
	
 	Агент = ТекДанные["ОсновнойМенеджерПокупателя"];
	КодАгента = ПолучитьКодАгента(Агент);
	
	Если КодАгента = "" Тогда Возврат; КонецЕсли; 
	
	Агент = Строка(Агент);
	
	Картинка = Элементы.Декорация1.Картинка; //картинка для индикатора
	КаталогФото = ПолучитьКаталогФото(КодАгента, КаталогЛогФайлов); //каталог, где хранятся фото агента, может быть сетевым, но должен быть доступен на сервере
	СоздатьКаталог(ПапкаМоиДокументы + "\Agents\" + СокрЛП(КодАгента) + "\Photo\Clients"); //создает  папки агента на локальном компьютере в Моих документах. Процедура получения папки Мои документы ниже 
	Файлы = ПолучитьФотографииОбъектовСервер(КаталогФото); //функция на сервере которая получает список всех изображений в папке агента
	Количество = Файлы.Количество();
	Загружено = 0;
	Проверено = 0;
	Шаг = Количество/100;
	Для Каждого Файл из Файлы Цикл
		ОбработкаПрерыванияПользователя();
		ИмяФайла = Файл.ПолноеИмя;
		ИмяФайлаКлиент = СохранитьФайлЛокально(ИмяФайла, Проверено, Загружено); //загружает, если надо файл локально
		Состояние("Проверено: " + Проверено + " из " + Количество + ". Загружено новых: " + Загружено, Проверено/шаг, Агент + " (прервать - CTRL+Break)", Картинка);		
	КонецЦикла;
	Сообщить(""+ Агент + ". Проверено: " + Проверено + ". Загружено новых: " + Загружено);	
КонецПроцедуры

&НаКлиенте
Функция МоиДокументы()
    
    Попытка
        WshShell = Новый COMОбъект("Wscript.Shell");
        WshFolder = WshShell.SpecialFolders.Item("MyDocuments");
        Возврат WshFolder;
    Исключение
        Возврат "";
    КонецПопытки;
    
КонецФункции

&НаКлиенте
Функция СохранитьФайлЛокально(ИмяФайла, Проверено = 0, Загружено = 0) 
	ИмяФайлаКлиент = ПолучитьИмяФайлаКлиент(ИмяФайла);
	Проверено = Проверено + 1;
	Если НайтиФайлы(ИмяФайлаКлиент).Количество() <> 0 Тогда
		Возврат(ИмяФайлаКлиент);
	КонецЕсли;
	АдресФайла = ФайлВоВременноеХранилищеСервер(ИмяФайла);
	ПолучитьФайл(АдресФайла, ИмяФайлаКлиент, Ложь);
	Сообщить("Сохранили: " + ИмяФайлаКлиент); 
	УдалитьИзВременногоХранилища(АдресФайла);		
	Загружено = Загружено + 1;
	Возврат(ИмяФайлаКлиент);
КонецФункции

&НаКлиенте
Функция ПолучитьИмяФайлаКлиент(ИмяФайла)
	Возврат(СтрЗаменить(ИмяФайла, КаталогЛогФайлов, ПапкаМоиДокументы + "\"));
КонецФункции

&НаСервереБезКонтекста
Функция ФайлВоВременноеХранилищеСервер(ИмяФайла)

	Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайла));	
	Возврат(Адрес);

КонецФункции // ФайлВоВременноеХранилище()

Обновление списка файлов:

 

&НаКлиенте
Процедура ОбновитьСписокФото(Команда)
	
	СписокФото.Очистить();
	ТекДанные = Элементы.СписокКонтрагентов.ТекущиеДанные;
	Если ТекДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	КодАгента	= ПолучитьКодАгента(ТекДанные["ОсновнойМенеджерПокупателя"]);
	КаталогФото 	= ПолучитьКаталогФото(КодАгента, КаталогЛогФайлов);
	Если ТипЗнч(ТекДанные) = Тип("СправочникСсылка.Контрагенты") Тогда
		КодКонтрагента = СокрЛП(ТекДанные.Код);
	Иначе
		КодКонтрагента = "";
	КонецЕсли;
	Файлы = ПолучитьФотографииОбъектовСервер(КаталогФото, КодКонтрагента); //список фото на сервере, возвращает массив с элементами типа Структура, чтобы протащить их с сервера на клиент
	СоздатьКаталог(ПапкаМоиДокументы + "\Agents\" + СокрЛП(КодАгента) + "\Photo\Clients"); //создаем на всякий случай, т.к. при просмотре отсутствующие локально фото сохраняются
	Для Каждого Файл из Файлы Цикл //далее в цикле разбираем имя файла на части, алгоритм от Моби-С
		ФайлСтр = Файл.ИмяБезРасширения;
		Комп = СтрЗаменить(ФайлСтр, "_", Символы.ПС);
		Дата = СтрПолучитьСтроку(Комп, 2);
		Время = СтрПолучитьСтроку(Комп,3);
		ДатаФайла = Дата(Прав(Дата, 4), Сред(Дата, 3, 2), Лев(Дата, 2), Лев(Время, 2), Сред(Время, 3, 2), Прав(Время, 2));
		ДатаФайла = КонвертироватьUTCВремяВЛокальное(ДатаФайла, 99);
		Если НЕ ((ДатаФото1 = '00010101' Или ДатаФайла >= НачалоДня(ДатаФото1)) И (ДатаФото2 = '00010101' ИЛИ ДатаФайла  "" И КодОбъекта <> КодКонтрагента Тогда Продолжить; КонецЕсли;
		Контрагент = ПолучитьКонтрагента(КодОбъекта);
		стр = СписокФото.Добавить();
		стр.ИмяФайла = Файл.ПолноеИмя;
		стр.Дата = ДатаФайла;
		стр.Контрагент = Контрагент;
	КонецЦикла;

	СписокФото.Сортировать("Дата");
	
КонецПроцедуры


Генерация html-кода при  выборе фотографии

 

&НаКлиенте
Процедура УстановитьТекстHTMLСФото(СсылкаНаКартинку)
	СтрокаМасштаба = "width='";
	
	Попытка //пытаемся получить размеры фото, чтобы выяснить по ширине или высоте масштабировать
		Image = Новый COMОбъект("WIA.ImageFile");
		Image.LoadFile(СсылкаНаКартинку);
		Если Image.Height > Image.width Тогда
			СтрокаМасштаба = "height='";
		КонецЕсли;
		Image = "";
	Исключение
	КонецПопытки;
	СтрокаМасштаба = СтрокаМасштаба + Масштаб + "%'"; //в зависимости от реквизита формы, который обычно 100
	Фото = "
        |
        |
        |
        |


        |
        |"; КонецПроцедуры // УстановитьТекстHTMLСФото()

Поворот изображения

 

&НаКлиенте
Процедура ПовернутьФото(Градус) //описание есть в мое публикации про сканирование

	Если Элементы.СписокФото.ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ИмяФайла = Элементы.СписокФото.ТекущиеДанные.ИмяФайла;
	ИмяФайла = ПолучитьИмяФайлаКлиент(ИмяФайла);
	Если НайтиФайлы(ИмяФайла).Количество() = 0 Тогда
		Сообщить("Нечего поворачивать");
		Возврат;
	КонецЕсли;
	
	Image = Новый COMОбъект("WIA.ImageFile");
 	Image.LoadFile(ИмяФайла);
	
	Если Image = Неопределено Тогда
        Возврат;
    КонецЕсли;

    IP = Новый COMОбъект("WIA.ImageProcess"); //создаем объект WIA для редактирования изображения
    IP.Filters.Add(IP.FilterInfos("RotateFlip").FilterID); //создаем WIA-фильтр для поворота
    IP1 = IP.Filters(1);
    Для К = 1 По IP1.Properties.Count Цикл
        Если IP1.Properties(К).Name = "RotationAngle" Тогда
            IP1.Properties(К).Value = Градус; //вертеть можно на 90,180 и 270 грудосов
            Прервать;
        КонецЕсли;
    КонецЦикла;

    Image = IP.Apply(Image);
	КопироватьФайл(ИмяФайла, ИмяФайла + "1");
	УдалитьФайлы(ИмяФайла);
	Image.SaveFile(ИмяФайла);
	УдалитьФайлы(ИмяФайла + "1");
	ОбновитьФото();
	Image = "";
	IP = "";
	IP1 = "";
	
КонецПроцедуры
 

Открытие в программе просмотра изображений

&НаКлиенте
Процедура ОткрытьФото(Команда)
	ЗапуститьПриложение(Элементы.СписокФото.ТекущиеДанные.ИмяФайла);
КонецПроцедуры

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
mavПросмотрФотоМобиС.epf
.epf 22,88Kb
28.11.13
17
.epf 22,88Kb 17 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Сергей Кудашкин (sikuda) 28.11.13 09:34
А почему не засунуть все фото на сервере во временное хралилище и пользуясь кэшом браузера показывать их в HTML поле? Типа < img src='"+СсылкаНаКартинку+"'/ >
2. Александр Медведев (anig99) 28.11.13 10:05
(1) кэш браузера не очень надежная вещь + так заранее нельзя подгрузить все фото. Кроме того, нужно придумывать как сделать, чтобы навигационные ссылки были одинаковые в разных сеансах. А так, как раз подгружать приходиться только НОВЫЕ фото.
3. Антон (anton.fly7) 28.11.13 16:48
а возможно как то в тонком клиенте вставить изображение из буфера обмена и передать его на сервер? в идеале хотелось бы делать это в веб-браузере, но тонкий тоже подойдет
4. Александр Медведев (anig99) 28.11.13 17:10
(3) копать в эту сторону. http://help1c.com/faq/view/705.html
Если удастся буфер в двоичные данные перегнать, то можно и на сервер отправить.
5. Александр Медведев (anig99) 02.12.13 11:46
упорно не хочет вставлять код в процедуре УстановитьТекстHTMLСФото
Фото = "
	    |<!DOCTYPE html>
	    |<html>
	    |<body>
	    |<img src='" + СсылкаНаКартинку + "' " + СтрокаМасштаба + ">
	    |</body>
	    |</html>";
...Показать Скрыть
6. Сергей Кудашкин (sikuda) 20.12.13 17:28
(5) anig99, Доделал свой просмоторщик без COM+.
Если размер легко поменять, то поворот это только CSS3 и тонкий клиент 1С в пролете.
Но это разве может нас остановить http://infostart.ru/public/242659/
7. Виталий Сорокин (mastersva) 27.02.14 09:07
Подскажите, а как обстоит ситуация с оперативной памятью, просто при просмотре через поле картинки на управляемой форме память растет как на дрожжах.
8. Александр Медведев (anig99) 27.02.14 12:36
(7) не проверял, но тут не поле картинки. Вроде лучше должно быть
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа