Как отобразить картинку из табличного документа в поле HTML документа в 1С 8.3?

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

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

Выясним причину ошибки

Проанализируем механизм сохранения табличного документа платформой 1С. Когда выполняется метод ТабличныйДокумент.Записать() с типом ТипФайлаТабличногоДокумента.HTML или HTML4, платформа формирует не один файл, а сохраняет HTML-разметку и создает рядом отдельный каталог с ресурсами вида ИмяФайла_files. В этот каталог помещаются все графические объекты документа под именами image001.png, image002.png и так далее.

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

Способ 1. Автоматическая замена путей на формат Base64 (Data URI)

Рассмотрим наиболее надежный и универсальный метод, который отлично работает как в тонком клиенте, так и в веб-клиенте. Идея заключается в том, чтобы после сохранения файла на диск прочитать созданные графические файлы, преобразовать их в строку формата Base64 и внедрить непосредственно в тело HTML-кода.

Посмотрим на пример программного кода, реализующего этот алгоритм:


ИмяФайла = ПолучитьИмяВременногоФайла("html");
ТабДокумент.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.HTML);

ФайлHTML = Новый Файл(ИмяФайла);
КаталогРесурсов = ФайлHTML.ИмяБезРасширения + "_files";
ПутьКФайлу = ФайлHTML.Путь;

ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.Прочитать(ИмяФайла);
ТекстHTML = ТекстДок.ПолучитьТекст();

Индекс = Найти(ТекстHTML, КаталогРесурсов);
Пока Индекс <> 0 Цикл
    ПозицияКавычки = Найти(Сред(ТекстHTML, Индекс), """");
    Если ПозицияКавычки <> 0 Тогда
        ОтносительныйПуть = Сред(ТекстHTML, Индекс, ПозицияКавычки - 1);
        ПолныйПутьКФайлу = ПутьКФайлу + ОтносительныйПуть;
        
        Если Новый Файл(ПолныйПутьКФайлу).Существует() Тогда
            ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПолныйПутьКФайлу);
            СтрокаBase64 = "data:image/png;base64," + Base64Строка(ДвоичныеДанныеФайла);
            ТекстHTML = СтрЗаменить(ТекстHTML, ОтносительныйПуть, СтрокаBase64);
        КонецЕсли;
    КонецЕсли;
    
    Индекс = Найти(ТекстHTML, КаталогРесурсов);
КонецЦикла;

// Передаем итоговый текст в реквизит формы, привязанный к полю HTML
ЭлементФормыТекстHTML = ТекстHTML;

// Очищаем временные файлы
УдалитьФайлы(ИмяФайла);
УдалитьФайлы(ПутьКФайлу + КаталогРесурсов);

Способ 2. Добавление тега base в заголовок страницы

Рассмотрим подробнее второй вариант. Если не требуется передавать разметку в автономном виде, можно указать браузерному движку исходный каталог, откуда следует загружать ресурсы с относительными путями. Для этого в тег <head> внедряется директива <base href="...">.

Разберем реализацию этого способа:


ИмяФайла = ПолучитьИмяВременногоФайла("html");
ТабДокумент.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.HTML);

ФайлHTML = Новый Файл(ИмяФайла);
ПутьККаталогу = "file:///" + СтрЗаменить(ФайлHTML.Путь, "\", "/");

ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.Прочитать(ИмяФайла);
ТекстHTML = ТекстДок.ПолучитьТекст();

// Вставляем базовый URL сразу после открывающего тега head
ТегБазовогоПути = "<head><base href=""" + ПутьККаталогу + """>";
ТекстHTML = СтрЗаменить(ТекстHTML, "<head>", ТегБазовогоПути);

ЭлементФормыТекстHTML = ТекстHTML;

Способ 3. Прямая загрузка локального файла через метод Перейти

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

Посмотрим на пример вызова метода:


ИмяФайла = ПолучитьИмяВременногоФайла("html");
ТабДокумент.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.HTML);

// Загружаем сохраненный файл напрямую в элемент управления
Элементы.ПолеHTML.Перейти(ИмяФайла);

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

Важные нюансы при работе в клиент-серверном режиме

Разберем ключевые технические моменты, на которые следует обратить внимание при реализации:

  1. Разделение контекстов: Если формирование табличного документа происходит в процедуре &НаСервере, временные файлы создаются в файловой системе сервера. Клиентское приложение не имеет к ним прямого доступа по локальным путям. Поэтому при серверном формировании рекомендуется использовать метод с конвертацией в Base64, возвращая на клиент уже полностью готовый текст страницы.
  2. Ограничения веб-клиента: В веб-клиенте политики безопасности браузеров блокируют доступ к локальным файлам по протоколу file://. Для браузеров единственным гарантированным решением остается кодирование в Base64.
  3. Очистка временных данных: При постоянной генерации отчетов временный каталог может переполняться. Всегда используйте метод УдалитьФайлы() после того, как двоичные данные или текст были прочитаны в память.
← На главную