Как в 1С сохранить картинку на клиент без создания временных файлов на сервере?

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

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

Почему возникает ошибка при использовании Временного хранилища?

Посмотрим на классический подход разработчика. Обычно для передачи файла с сервера на клиент мы помещаем его во временное хранилище с помощью метода ПоместитьВоВременноеХранилище, а затем забираем на клиенте. Но в нашем случае этот код выдает ошибку доступа к каталогу. Почему так происходит?

Метод работы с временным хранилищем только звучит так, будто он функционирует исключительно в оперативной памяти (ОЗУ). На самом деле, платформа 1С регулярно кэширует сеансовые данные и пытается сбросить содержимое временного хранилища на жесткий диск сервера в каталог временных файлов (папка %TEMP% в Windows или /tmp в Linux). Если системные администраторы полностью закрыли права на запись или запретили создание файлов даже в системных temp-каталогах, платформенный механизм не сможет отработать и ожидаемо вернет ошибку.

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

Способ 1. Прямой возврат Двоичных Данных с сервера

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

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

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


// На сервере
Функция ПолучитьКартинкуССервера(СсылкаНаНоменклатуру) Экспорт
    
    // Получаем картинку из хранилища
    Картинка = СсылкаНаНоменклатуру.ФайлКартинки.Хранилище.Получить();
    Если Картинка <> Неопределено Тогда
        Возврат Картинка.ПолучитьДвоичныеДанные();
    КонецЕсли;
    
    Возврат Неопределено;
    
КонецФункции

// На клиенте
Процедура СохранитьКартинкуНаКлиенте()
    
    ДвоичныеДанныеКартинки = ПолучитьКартинкуССервера(ВыбраннаяНоменклатура);
    
    Если ДвоичныеДанныеКартинки <> Неопределено Тогда
        // Сразу пишем на локальный диск клиента
        ПутьСохранения = "C:\Users\Client\Pictures\Image.jpg";
        ДвоичныеДанныеКартинки.Записать(ПутьСохранения);
    КонецЕсли;

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

Способ 2. Передача файлов через строку Base64

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

Данный алгоритм преобразует любые байты в безопасный текстовый формат. Строка гарантированно передастся с сервера на клиент как обычное значение функции. Этот способ увеличивает объем передаваемых данных примерно на 30-33%, но для картинок номенклатуры это обычно не критично.

Проанализируем по шагам, как это работает:

  1. На сервере получаем картинку в виде объекта ДвоичныеДанные.
  2. Затем эти данные конвертируются в обычную строку встроенной функцией Base64Строка().
  3. Текстовая строка возвращается на клиент.
  4. На клиенте строка раскодируется обратно встроенной функцией Base64Значение() и сохраняется.

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


// На сервере
Функция ПолучитьКартинкуВBase64(СсылкаНаНоменклатуру) Экспорт
    
    ДанныеКартинки = СсылкаНаНоменклатуру.ФайлКартинки.Хранилище.Получить();
    Если ДанныеКартинки <> Неопределено Тогда
        ДвоичныеДанные = ДанныеКартинки.ПолучитьДвоичныеДанные();
        // Преобразуем двоичные данные в строку Base64
        Возврат Base64Строка(ДвоичныеДанные);
    КонецЕсли;
    
    Возврат "";
    
КонецФункции

// На клиенте
Процедура СохранитьКартинкуBase64()
    
    СтрокаBase64 = ПолучитьКартинкуВBase64(ВыбраннаяНоменклатура);
    
    Если Не ПустаяСтрока(СтрокаBase64) Тогда
        // Преобразуем строку обратно в двоичные данные на клиенте
        ДвоичныеДанныеКартинки = Base64Значение(СтрокаBase64);
        ПутьСохранения = "C:\Users\Client\Pictures\Image_Base64.jpg";
        ДвоичныеДанныеКартинки.Записать(ПутьСохранения);
    КонецЕсли;

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

Способ 3. Использование потоков в памяти (с версии 1С 8.3.9)

Если у вас современная версия платформы, рассмотрим работу с потоками данных. В платформе 1С реализованы мощные объекты для потоковой работы с данными исключительно в оперативной памяти — ПотокВПамяти, БуферДвоичныхДанных и ЧтениеДанных.

Этот способ отлично подходит, если данные перед отправкой на клиент нужно как-то обработать: собрать из нескольких кусков, упаковать в архив (ZIP умеет работать с потоками) или модифицировать, не создавая временных файлов.

Вы получаете данные, помещаете их в поток, делаете все манипуляции в ОЗУ, а затем передаете на клиент, извлекая их через метод ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(). Никаких неявных попыток создать кэш-файлы со стороны 1С не произойдет.

Способ 4. Альтернативные пути: HTTP или FTP

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

Сервер 1С может напрямую отправить двоичные данные файла POST-запросом на сторонний корпоративный веб-сервер, или записать их по протоколу FTP. Оттуда клиентская машина (или другое приложение) сможет их скачать стандартными средствами. При использовании объекта HTTPСоединение платформа также позволяет передавать ДвоичныеДанные в теле запроса без их предварительного сохранения на диск.

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

← На главную