В процессе разработки часто возникает задача загрузить изображение, находящееся в файле, и использовать его в 1С, например, для вывода в корректно сформированную печатную форму на БСП. На клиенте это делается очень просто с помощью конструктора Новый Картинка(ПутьКФайлу). Однако при попытке выполнить тот же код на сервере (в процедуре с директивой &НаСервере) разработчик сталкивается с ошибкой. Давайте разберемся, почему так происходит и как правильно загружать изображения в серверном коде.
Основная причина ограничения заключается в архитектуре и безопасности клиент-серверного взаимодействия. Серверный процесс 1С не имеет прямого доступа к файловой системе клиента, а его доступ к собственной файловой системе может быть ограничен правами пользователя, от имени которого он запущен. Поэтому платформа запрещает использование конструктора по пути к файлу в серверном контексте. Но это не значит, что задача нерешаема. Рассмотрим два основных сценария.
Это как раз та ситуация, о которой спрашивал автор темы. Файл с картинкой уже лежит на диске сервера 1С или в сетевой папке, доступной серверу. Наша текущая задача — прочитать файл и преобразовать его в объект типа Картинка.
Для этого мы будем использовать двухэтапный подход с промежуточным объектом ДвоичныеДанные. Этот объект является универсальным контейнером для данных любого файла и доступен для использования как на клиенте, так и на сервере.
Разберем по шагам:
ДвоичныеДанные.Картинка, используя другой вариант его конструктора.Посмотрим на пример серверной процедуры, которая выполняет эти действия.
&НаСервере
Процедура ЗагрузитьКартинкуССервера()
// Указываем путь к файлу.
// ВАЖНО: этот путь должен быть виден и доступен для пользователя,
// от имени которого запущен серверный процесс 1С (rphost).
ПутьКФайлуНаСервере = "C:\Temp\logo.png"; // Пример локального пути
// ПутьКФайлуНаСервере = "\\fileserver\share\images\logo.png"; // Пример сетевого пути
Перем ГотоваяКартинка;
Попытка
// Шаг 1: Читаем файл в двоичные данные
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлуНаСервере);
// Шаг 2: Создаем объект "Картинка" из двоичных данных
ГотоваяКартинка = Новый Картинка(ДвоичныеДанныеФайла);
Исключение
// Если файл не найден, недоступен или имеет неверный формат,
// программа сообщит об ошибке, но не "упадет".
Сообщить("Не удалось загрузить изображение из файла: " + ПутьКФайлуНаСервере);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
// Теперь переменная "ГотоваяКартинка" содержит нужный нам объект.
// Мы можем, например, вставить его в макет печатной формы.
// Предположим, у нас есть макет и в нем рисунок с именем "ЛоготипКомпании".
// ТабДокумент = Новый ТабличныйДокумент;
// Макет = ПолучитьМакет("МойМакет");
// ОбластьМакета = Макет.ПолучитьОбласть("Шапка");
// ОбластьМакета.Рисунки.ЛоготипКомпании.Картинка = ГотоваяКартинка;
// ТабДокумент.Вывести(ОбластьМакета);
Сообщить("Картинка успешно загружена и готова к использованию!");
КонецПроцедуры
Важный момент: всегда оборачивайте код работы с файлами в блок Попытка...Исключение. Это позволит корректно обработать ситуации, когда файл отсутствует, к нему нет доступа или он поврежден, и избежать аварийного завершения операции.
Часто бывает необходимо, чтобы пользователь сам выбрал файл на своем компьютере. Помимо стандартного диалога, вы можете реализовать Drag & Drop для переноса картинки на форму с помощью мыши. Как мы уже выяснили, сервер 1С не может напрямую "заглянуть" на диск пользователя. Для этого в платформе предусмотрен специальный механизм передачи данных через временное хранилище.
Проанализируем алгоритм этого процесса.
НачатьПомещениеФайлаНаСервер(). Этот метод не блокирует интерфейс пользователя на время загрузки.Картинка, точно так же, как в первом сценарии.Давайте посмотрим на пример реализации. Допустим, на форме есть кнопка "Загрузить картинку".
// Клиентская процедура, обработчик нажатия кнопки
&НаКлиенте
Процедура ЗагрузитьКартинкуСКлиента(Команда)
// Создаем описание оповещения. Оно указывает, какую процедуру нужно вызвать
// после завершения операции помещения файла.
// Первый параметр - имя экспортной процедуры-обработчика.
// Второй параметр - модуль, где она находится (в данном случае, эта же форма).
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайлаНаСервер", ЭтаФорма);
// Запускаем диалог выбора файла и асинхронную передачу на сервер
НачатьПомещениеФайлаНаСервер(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
// Серверная процедура, которая будет вызвана после успешной загрузки файла
&НаСервере
Процедура ПослеПомещенияФайлаНаСервер(Результат, Адрес, ДополнительныеПараметры) Экспорт
Если Не Результат Тогда
// Если при передаче файла произошла ошибка, Результат будет Ложь
Сообщить("Во время передачи файла произошла ошибка.");
Возврат;
КонецЕсли;
// Адрес - это строка, содержащая адрес файла во временном хранилище.
// Теперь мы можем получить двоичные данные по этому адресу.
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(Адрес);
Если ДвоичныеДанныеФайла = Неопределено Тогда
Сообщить("Не удалось получить данные файла из временного хранилища.");
Возврат;
КонецЕсли;
// А дальше все так же, как и в первом сценарии!
Попытка
ГотоваяКартинка = Новый Картинка(ДвоичныеДанныеФайла);
// Здесь мы можем сохранить картинку в реквизит объекта
// или сразу использовать для формирования печатной формы.
// Например, сохраним ее в реквизит объекта с типом ХранилищеЗначения.
// РеквизитОбъектаКартинка = Новый ХранилищеЗначения(ГотоваяКартинка);
Сообщить("Картинка с компьютера пользователя успешно загружена на сервер!");
Исключение
Сообщить("Ошибка создания картинки. Возможно, выбранный файл не является изображением.");
КонецПопытки;
КонецПроцедуры
Под словом "обработать", как выяснилось в обсуждении, чаще всего подразумевается простое помещение картинки в макет печатной формы. Как это сделать, мы показали в первом примере. Объект Картинка присваивается свойству Картинка элемента-рисунка в области табличного документа.
После загрузки и обработки картинку нужно где-то сохранить. Существует два основных подхода:
ХранилищеЗначения. В него помещаются либо непосредственно двоичные данные, либо сам объект Картинка. Для обратной задачи — извлечения данных — пригодится обработка для выгрузки любых прикрепленных файлов.Таким образом, мы рассмотрели надежные и правильные способы загрузки изображений в серверном коде 1С, разобрав как случай с файлом на сервере, так и с файлом на компьютере пользователя.