При разработке прикладных решений на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда поле HTML документа отлично отображает графику в файловом варианте базы, но «теряет» её при переходе на клиент-серверный вариант. Особенно остро эта проблема проявилась в последних релизах платформы (начиная с 8.3.21 и выше, включая 8.3.27), где механизмы безопасности стали значительно строже. Разберем подробно, почему это происходит и какие существуют методы решения данной задачи.
Для начала проанализируем ситуацию, описанную в сообщениях форума. Основная причина того, что картинка не отображается в клиент-серверном варианте, заключается в разделении контекстов исполнения. Когда мы формируем HTML-код на стороне сервера, мы оперируем путями к файлам, которые доступны серверу (например, временные папки пользователя, под которым запущен сервер 1С). Однако само поле HTML документа — это визуальный компонент, который отрисовывается на стороне клиента (в тонком или толстом клиенте).
Рассмотрим типичный сценарий: сервер формирует файл картинки в своей временной папке C:\Users\USR1CV8\AppData\Local\Temp\... и вставляет этот путь в тег <img>. Когда клиентское приложение пытается отобразить этот HTML, оно ищет файл по указанному пути на локальном компьютере пользователя. Естественно, там этого файла нет, и пользователь видит «пустой квадрат».
Ситуация осложняется в новых версиях платформы (8.3.21, 8.3.24, 8.3.27). Платформа перешла на обновленный движок Chromium. В целях безопасности встроенный браузер теперь блокирует загрузку любых ресурсов по протоколу file://. Даже если вы программно передадите файл с сервера на клиент и положите его в локальную папку пользователя, при попытке подставить прямой путь в HTML вы получите ошибку: «В целях безопасности загрузка по файловому протоколу заблокирована».
Проанализируем наиболее универсальный способ, который рекомендуют опытные разработчики. Чтобы не зависеть от файловой системы клиента или сервера и обойти ограничения протокола file://, мы можем внедрить данные картинки непосредственно в тело HTML-кода в виде строки. Для этого используется кодирование Base64.
Выясним, как это реализовать пошагово. Сначала нам нужно получить двоичные данные картинки, затем преобразовать их в строку и подставить в атрибут src тега img.
Посмотрим на пример кода, который реализует этот механизм:
// 1. Получаем двоичные данные из хранилища или файла
ДвоичныеДанныеКартинки = Справочники.Изображения.ПолучитьДанные(СсылкаНаКартинку);
// 2. Преобразуем в строку Base64
СтрокаBase64 = Base64Строка(ДвоичныеДанныеКартинки);
// 3. Формируем текст HTML с внедренной картинкой
// Необходимо указать MIME-тип (например, image/jpeg или image/png)
ТекстHTML = "<html><body>";
ТекстHTML = ТекстHTML + "<img src=""data:image/jpeg;base64," + СтрокаBase64 + """ />";
ТекстHTML = ТекстHTML + "</body></html>";
// 4. Устанавливаем текст в поле HTML документа
Элементы.ПолеHTMLПросмотр.УстановитьТекст(ТекстHTML);
Преимущества этого метода:
Temp.file:// в новых версиях платформы.Важный нюанс: Если картинок очень много или они имеют большой размер, это может замедлить работу формы и увеличить потребление памяти. В таких случаях рекомендуется предварительно сжимать изображения на сервере перед конвертацией.
Рассмотрим альтернативный вариант, который обсуждался в сообщениях. Если по каким-то причинам Base64 вам не подходит, необходимо обеспечить физическое наличие файла на клиентской машине. Однако помните о блокировках платформы 8.3.27! Этот метод будет работать стабильно только в старых релизах или при специфических настройках.
Алгоритм действий следующий:
ПоместитьВоВременноеХранилище.&НаКлиенте) получаем данные из хранилища и записываем их в локальный временный файл.Пример реализации передачи:
&НаСервере
Функция ПодготовитьКартинкуНаСервере()
КартинкаОбъект = Справочники.Файлы.НайтиПоНаименованию("Логотип").Данные.Получить();
Возврат ПоместитьВоВременноеХранилище(КартинкаОбъект, ЭтаФорма.УникальныйИдентификатор);
КонецФункции
&НаКлиенте
Процедура ОтобразитьHTML()
АдресХранилища = ПодготовитьКартинкуНаСервере();
// Получаем путь к временному файлу на стороне КЛИЕНТА
ИмяФайла = ПолучитьИмяВременногоФайла("jpg");
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
Данные.Записать(ИмяФайла);
// Внимание: на новых платформах прямой путь может быть заблокирован!
ТекстHTML = "... <img src=""" + ИмяФайла + """> ...";
Элементы.ПолеHTML.УстановитьТекст(ТекстHTML);
КонецПроцедуры
В сообщении №10 пользователь отмечает, что раньше отлично работал метод с навигационными ссылками вида e1cib/data/Справочник.Изображения.Данные?ref=.... Это был очень удобный способ, так как платформа сама брала на себя заботу о доставке данных.
Проанализируем ситуацию: начиная с версии 8.3.21, из-за перехода на Chromium, механизм изоляции содержимого поля HTML стал жестче. Прямая подстановка ссылки e1cib в тег img часто приводит к тому, что картинка не отрисовывается, так как контекст безопасности браузера внутри 1С не считает эту ссылку доверенной или доступной без явной авторизации внутри сессии браузера.
Как быть в версии 8.3.27?
Если навигационные ссылки перестали работать, самым правильным решением будет вернуться к Решению №1 (Base64). Это единственный способ гарантировать отображение картинки во всех вариантах работы: тонкий клиент, толстый клиент и веб-клиент.
Если ваша задача включает поддержку веб-клиента, следует помнить о правилах CORS (Cross-Origin Resource Sharing). Браузер (Chrome, Firefox) не позволит загрузить картинку с другого домена или локального диска. В этом случае Base64 также является фаворитом. Однако навигационные ссылки e1cib в веб-клиенте обычно работают лучше, чем в тонком клиенте, так как браузер уже находится в контексте веб-сервера 1С.
Подводя итог нашему разбору, выделим ключевые правила для работы с графикой в HTML-полях 1С:
Base64. Это избавляет от проблем с путями, правами доступа и протоколами безопасности.file:// закрыт. Не пытайтесь подставлять пути типа C:\Temp\img.jpg.УстановитьТекст().Использование данных подходов позволит вам создавать надежные и визуально привлекательные интерфейсы, которые будут стабильно работать вне зависимости от режима запуска или версии платформы 1С.