Как программно загрузить картинку из файла на сервере 1С?

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

В процессе разработки часто возникает задача загрузить изображение, находящееся в файле, и использовать его в 1С, например, для вывода в корректно сформированную печатную форму на БСП. На клиенте это делается очень просто с помощью конструктора Новый Картинка(ПутьКФайлу). Однако при попытке выполнить тот же код на сервере (в процедуре с директивой &НаСервере) разработчик сталкивается с ошибкой. Давайте разберемся, почему так происходит и как правильно загружать изображения в серверном коде.

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

Сценарий 1: Файл изображения находится на сервере

Это как раз та ситуация, о которой спрашивал автор темы. Файл с картинкой уже лежит на диске сервера 1С или в сетевой папке, доступной серверу. Наша текущая задача — прочитать файл и преобразовать его в объект типа Картинка.

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

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

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

Посмотрим на пример серверной процедуры, которая выполняет эти действия.


&НаСервере
Процедура ЗагрузитьКартинкуССервера()
    // Указываем путь к файлу. 
    // ВАЖНО: этот путь должен быть виден и доступен для пользователя, 
    // от имени которого запущен серверный процесс 1С (rphost).
    ПутьКФайлуНаСервере = "C:\Temp\logo.png"; // Пример локального пути
    // ПутьКФайлуНаСервере = "\\fileserver\share\images\logo.png"; // Пример сетевого пути

    Перем ГотоваяКартинка;

    Попытка
        // Шаг 1: Читаем файл в двоичные данные
        ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлуНаСервере);

        // Шаг 2: Создаем объект "Картинка" из двоичных данных
        ГотоваяКартинка = Новый Картинка(ДвоичныеДанныеФайла);

    Исключение
        // Если файл не найден, недоступен или имеет неверный формат,
        // программа сообщит об ошибке, но не "упадет".
        Сообщить("Не удалось загрузить изображение из файла: " + ПутьКФайлуНаСервере);
        Сообщить(ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    // Теперь переменная "ГотоваяКартинка" содержит нужный нам объект.
    // Мы можем, например, вставить его в макет печатной формы.
    // Предположим, у нас есть макет и в нем рисунок с именем "ЛоготипКомпании".
    
    // ТабДокумент = Новый ТабличныйДокумент;
    // Макет = ПолучитьМакет("МойМакет");
    // ОбластьМакета = Макет.ПолучитьОбласть("Шапка");
    // ОбластьМакета.Рисунки.ЛоготипКомпании.Картинка = ГотоваяКартинка;
    // ТабДокумент.Вывести(ОбластьМакета);
    
    Сообщить("Картинка успешно загружена и готова к использованию!");

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

Важный момент: всегда оборачивайте код работы с файлами в блок Попытка...Исключение. Это позволит корректно обработать ситуации, когда файл отсутствует, к нему нет доступа или он поврежден, и избежать аварийного завершения операции.

Сценарий 2: Файл изображения находится на компьютере пользователя

Часто бывает необходимо, чтобы пользователь сам выбрал файл на своем компьютере. Помимо стандартного диалога, вы можете реализовать Drag & Drop для переноса картинки на форму с помощью мыши. Как мы уже выяснили, сервер 1С не может напрямую "заглянуть" на диск пользователя. Для этого в платформе предусмотрен специальный механизм передачи данных через временное хранилище.

Проанализируем алгоритм этого процесса.

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

Давайте посмотрим на пример реализации. Допустим, на форме есть кнопка "Загрузить картинку".


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

// Серверная процедура, которая будет вызвана после успешной загрузки файла
&НаСервере
Процедура ПослеПомещенияФайлаНаСервер(Результат, Адрес, ДополнительныеПараметры) Экспорт

    Если Не Результат Тогда
        // Если при передаче файла произошла ошибка, Результат будет Ложь
        Сообщить("Во время передачи файла произошла ошибка.");
        Возврат;
    КонецЕсли;

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

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

Дальнейшая работа с картинкой: обработка и хранение

Под словом "обработать", как выяснилось в обсуждении, чаще всего подразумевается простое помещение картинки в макет печатной формы. Как это сделать, мы показали в первом примере. Объект Картинка присваивается свойству Картинка элемента-рисунка в области табличного документа.

После загрузки и обработки картинку нужно где-то сохранить. Существует два основных подхода:

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

← На главную