Как добавить фильтр по расширениям при интерактивном выборе картинки в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Использование современного асинхронного метода ПоместитьФайлНаСерверАсинх

Начиная с версии платформы 8.3.15, устаревший метод НачатьПомещениеФайла не рекомендуется к использованию. Вместо него для загрузки одного файла эффективнее всего применять асинхронную конструкцию с директивой Асинх и оператором Ждать вместе с методом ПоместитьФайлНаСерверАсинх.

Для настройки параметров проводника операционной системы создадим объект ПараметрыДиалогаПомещенияФайлов. В нем укажем заголовок диалога, отключим множественный выбор и зададим маску фильтрации. Обратите особое внимание на правила формирования маски: расширения разделяются строго точкой с запятой (;), а не запятыми или пробелами.

Посмотрим на пример клиентского кода:


&НаКлиенте
Асинх Процедура ПрикрепитьКартинку(Команда)
    
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
    ПараметрыДиалога.Заголовок = "Выберите изображение";
    ПараметрыДиалога.МножественныйВыбор = Ложь;
    ПараметрыДиалога.Фильтр = "Файлы изображений (*.jpg;*.jpeg;*.png)|*.jpg;*.jpeg;*.png|Все файлы (*.*)|*.*";
    ПараметрыДиалога.ИндексФильтра = 0;
    
    Результат = Ждать ПоместитьФайлНаСерверАсинх(,,, ПараметрыДиалога, УникальныйИдентификатор);
    
    Если Результат = Неопределено Или Результат.ПомещениеФайлаОтменено Тогда
        Возврат;
    КонецЕсли;
    
    АдресКартинки = Результат.Адрес;
    
КонецПроцедуры

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

Способ 2. Использование метода НачатьПомещениеФайловНаСервер с описанием оповещения

Если в конфигурации используется стандарт разработки без ключевых слов асинхронности, либо требуется обеспечить совместимость с более ранними релизами 8.3, можно применить вызов через ОписаниеОповещения и метод НачатьПомещениеФайловНаСервер.

Рассмотрим реализацию данного варианта:


&НаКлиенте
Процедура ПрикрепитьКартинкуЧерезОповещение(Команда)
    
    ОповещениеОЗавершении = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
    
    СтрокаФильтра = "Изображения (*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg";
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов("Выберите изображение", Ложь, СтрокаФильтра);
    
    НачатьПомещениеФайловНаСервер(ОповещениеОЗавершении,,, ПараметрыДиалога, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораФайла(ПомещенныеФайлы, ДополнительныеПараметры) Экспорт
    
    Если ПомещенныеФайлы = Неопределено Или ПомещенныеФайлы.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    // Так как множественный выбор отключен, берем первый элемент коллекции
    АдресКартинки = ПомещенныеФайлы[0].Адрес;
    
КонецПроцедуры

Этот метод принимает коллекцию файлов, поэтому в процедуре обработки результата мы обращаемся к первому элементу массива через свойство ПомещенныеФайлы[0].Адрес.

Способ 3. Использование объекта ДиалогВыбораФайла

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

Разберем пример вызова диалога:


&НаКлиенте
Процедура ВыбратьПутьКФайлу(Команда)
    
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Выберите файл изображения";
    Диалог.МножественныйВыбор = Ложь;
    Диалог.ПроверятьСуществованиеФайла = Истина;
    Диалог.Фильтр = "Файлы изображений (*.png;*.jpg)|*.png;*.jpg";
    Диалог.ПредварительныйПросмотр = Истина;
    
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораВДиалоге", ЭтотОбъект);
    Диалог.Показать(Оповещение);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораВДиалоге(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныеФайлы = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ВыбранныйПуть = ВыбранныеФайлы[0];
    // Далее требуется отдельный вызов помещения файла во временное хранилище
    
КонецПроцедуры

Сохранение и серверная валидация данных

Выясним причину, почему одной лишь клиентской маски файлов недостаточно. Клиентский фильтр отсекает случайные действия пользователя, но пользователь может вручную сменить фильтр на «Все файлы» или прикрепить поврежденный файл с поддельным расширением. Поэтому при записи объекта на стороне сервера необходимо проверять двоичные данные перед их сохранением в реквизит с типом ХранилищеЗначения.

Рассмотрим серверную процедуру сохранения с проверкой корректности картинки и применением сжатия данных:


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

Важные рекомендации при работе с фильтрами файлов

  1. Синтаксис масок: В параметре фильтра имена масок обязательно разделяются точкой с запятой без пробелов: *.jpg;*.jpeg;*.png. Использование запятой приведет к тому, что операционная система не сможет распознать фильтр.
  2. Чувствительность к регистру: При работе пользователей на операционных системах Linux и macOS файловые системы чувствительны к регистру символов. Для надежности дублируйте расширения в верхнем регистре: *.jpg;*.JPG;*.png;*.PNG.
  3. Работа в веб-клиенте: Используйте объекты ПараметрыДиалогаПомещенияФайлов совместно с методами ПоместитьФайлНаСерверАсинх или НачатьПомещениеФайловНаСервер — они универсальны и работают во всех браузерах без запроса дополнительных модулей.
← На главную