Как выгрузить (экспортировать) картинку из 1С и затем удалить ее из реквизита объекта?

Программист 1С v8.3 (Управляемые формы) Торговля и дистрибуция
← К списку

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

Проблема, с которой мы часто сталкиваемся:

  1. Как получить двоичные данные картинки, хранящиеся в ХранилищеЗначения, и передать их на клиент для сохранения в файл?
  2. Как очистить реквизит объекта типа ХранилищеЗначения, содержащий картинку, если прямая запись в него из формы недоступна?

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

Выгрузка (экспорт) картинки из 1С на компьютер пользователя

Для выгрузки картинки нам потребуется организовать взаимодействие между клиентским и серверным кодом, используя механизм временного хранилища. Мы будем работать с реквизитом объекта, который хранит двоичные данные изображения в типе ХранилищеЗначения, например, Объект.СканПечати.

Рассмотрим подробнее шаги:

  1. Получение двоичных данных на сервере. Сначала нам нужно получить содержимое ХранилищеЗначения. Для этого используется метод Получить().
  2. Помещение данных во временное хранилище. Полученные двоичные данные необходимо поместить во временное хранилище на сервере. Это позволит передать их на клиент в виде уникального адреса. Для этого используем функцию ПоместитьВоВременноеХранилище().
  3. Передача адреса на клиент. Адрес временного хранилища возвращается на клиент, где он будет использован для запроса файла.
  4. Запрос файла на клиенте. На клиенте мы используем асинхронную функцию ПолучитьФайлССервераАсинх(), которая по переданному адресу временного хранилища загрузит файл на локальный компьютер пользователя.

Давайте посмотрим на пример кода, который реализует этот функционал. Предположим, у нас есть реквизит объекта СканПечати типа ХранилищеЗначения и строковый реквизит СканПечатиИмяФайла для хранения имени файла.


&НаКлиенте
Процедура ВыгрузитьОбразецПодписи(Команда)
    
    // 1. Вызываем серверную функцию для подготовки картинки
    АдресРезультата = ПодготовитьКартинку();
    
    // Проверяем, удалось ли получить адрес картинки
    Если Не ЗначениеЗаполнено(АдресРезультата) Тогда
        Возврат;
    КонецЕсли;
    
    // 2. Создаем параметры диалога для сохранения файла
    ПараметрыПолученияФайла = Новый ПараметрыДиалогаПолученияФайлов;
    
    // 3. Асинхронно получаем файл с сервера
    // Первый параметр - адрес во временном хранилище,
    // Второй - предлагаемое имя файла,
    // Третий - параметры диалога сохранения файла.
    ПолучитьФайлССервераАсинх(АдресРезультата, Объект.СканПечатиИмяФайла, ПараметрыПолученияФайла);
    
КонецПроцедуры        

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

Важные моменты при выгрузке:

Удаление (очистка) картинки из реквизита объекта

Задача очистки реквизита типа ХранилищеЗначения также требует серверного вызова, поскольку ХранилищеЗначения не доступно для прямой записи на клиенте. Мы рассмотрим два основных подхода к решению этой задачи.

Основной принцип: Для очистки реквизита типа ХранилищеЗначения необходимо присвоить ему новое значение Новый ХранилищеЗначения(Неопределено). Это фактически обнуляет ссылку на хранящиеся двоичные данные.

Метод 1: Использование методов РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы()

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

Разберем по шагам:

  1. Вызов серверной процедуры: На клиенте мы вызываем серверную процедуру для очистки.
  2. Получение изменяемой копии объекта: В серверной процедуре мы используем функцию РеквизитФормыВЗначение("Объект"). Эта функция создает изменяемую копию объекта данных формы.
  3. Очистка реквизитов: У полученной копии объекта мы присваиваем реквизиту СканПечати значение Новый ХранилищеЗначения(Неопределено) и очищаем имя файла СканПечатиИмяФайла.
  4. Сохранение изменений обратно в форму: С помощью функции ЗначениеВРеквизитФормы(ТекущийОбъект, "Объект") мы применяем изменения из нашей копии к реквизиту формы Объект. Это обновит отображение на форме, но не запишет объект в базу данных. Запись в базу произойдет позже, при вызове Записать().

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


&НаКлиенте
Процедура ОчиститьОбразецПодписи(Команда)
    
    // Вызываем серверную процедуру для очистки данных
    ОчиститьОбразецПодписиНаСервере();
    
    // Очищаем локальную ссылку на картинку, если она была отображена на форме
    // Например, если на форме есть элемент "ПолеКартинки" с привязкой к реквизиту "СсылкаНаКартинку"
    СсылкаНаКартинку = ""; 
    
КонецПроцедуры

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

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

Преимущества: Позволяет немедленно обновить данные на форме без необходимости записывать объект в базу данных. Изменения будут сохранены при следующей записи объекта.

Метод 2: Использование флага и обработчика события ПередЗаписьюНаСервере

Этот метод является одним из наиболее надежных и часто используемых для модификации данных объекта непосредственно перед его записью в базу. Он гарантирует, что изменения будут сохранены атомарно вместе с основной записью объекта.

Разберем по шагам:

  1. Добавление служебного реквизита: Мы добавляем в объект (например, в справочник или документ) дополнительный булевый реквизит, который будет служить флагом, например, УдалитьСканПриВыходе. Этот реквизит не обязательно выводить на форму.
  2. Установка флага на сервере: При нажатии кнопки "Очистить" на клиенте, мы вызываем серверную процедуру, которая устанавливает этот флаг в Истина.
  3. Обработка флага в ПередЗаписьюНаСервере: В обработчике события ПередЗаписьюНаСервере мы проверяем состояние нашего флага. Если он установлен, мы очищаем реквизиты СканПечати и СканПечатиИмяФайла, а затем сбрасываем флаг в Ложь.
  4. Запись объекта: После этого объект записывается в базу данных уже с очищенными реквизитами.

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


&НаКлиенте
Процедура ОчиститьОбразецПодписи(Команда)
    
    // Вызываем серверную процедуру для установки флага
    ОчиститьОбразецПодписиНаСервере();
    
    // Очищаем локальную ссылку на картинку, если она была отображена на форме
    СсылкаНаКартинку = ""; 
    
КонецПроцедуры

&НаСервере
Процедура ОчиститьОбразецПодписиНаСервере()

    // Устанавливаем флаг в объекте, который будет обработан при записи
    Объект.УдалитьСканПриВыходе = Истина;
 	
КонецПроцедуры

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

Важные моменты при использовании метода с флагом:

Заключение

Мы подробно разобрали, как эффективно работать с изображениями в 1С:Предприятие 8.3, используя клиент-серверное взаимодействие. Для выгрузки картинок мы используем механизм временного хранилища и асинхронную загрузку файла на клиент. Для удаления картинок из реквизитов типа ХранилищеЗначения мы рассмотрели два надежных метода: через функции РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы() для оперативного обновления формы, а также через служебный флаг и обработчик ПередЗаписьюНаСервере для гарантированной очистки при сохранении объекта.

Всегда помните о разделении контекстов выполнения (клиент/сервер) и используйте соответствующие методы для безопасной и корректной работы с данными в управляемых формах 1С.

← К списку