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