Встала задача дать возможность офису в другом городе просматривать фотографии сделанные торговыми агентами. Доступ к базе осуществляется через интернет с помощью тонкого клиента.
Система Моби-с загружает фотографии от торговых клиентов и хранит их в папках агентов. Фотографии могут быть привязаны как к товарам, так и к контрагентам. Интересовало именно фотографии привязанные к контрагентам. Привязка к контрагенту осуществляется через название файла.
Небольшое тестирование показало, что подгружать фотографии сразу в тонкий клиент слишком долго. Поэтому обработка сначала кэширует данные в папке Мои документы на локальном компьютере, куда сохраняет ещё не загруженные фотографии (с отбором по агенту). Кроме того, было выяснено, что предлагаемый 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 = "";
КонецПроцедуры
Открытие в программе просмотра изображений
&НаКлиенте
Процедура ОткрытьФото(Команда)
ЗапуститьПриложение(Элементы.СписокФото.ТекущиеДанные.ИмяФайла);
КонецПроцедуры