При разработке управляемых форм часто возникает задача отображения содержимого PDF-документов непосредственно внутри интерфейса 1С. Распространенным подходом является размещение на форме элемента Поле HTML-документа с передачей пути к временному файлу PDF. Однако разработчики нередко сталкиваются с ситуацией: на компьютере разработчика документ корректно открывается внутри формы, а у конечного пользователя при тех же действиях запускается отдельное окно внешней программы (например, Adobe Acrobat Reader).
Разберем детально, почему так происходит, какие механизмы операционной системы и платформы задействованы в этом процессе и как решить проблему.
Проанализируем классический программный алгоритм вывода файла, который используется во многих обработках:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Получаем двоичные данные файла из базы или хранилища
ДвоичныеДанныеФайла = ПолучитьФайлPDFИзБазы();
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Извлекаем файл во временный каталог на клиенте
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("pdf");
ДвоичныеДанные.Записать(ИмяВременногоФайла);
// Присваиваем путь реквизиту формы с типом "Строка", связанному с полем HTML
ПутьКФайлуHTML = ИмяВременногоФайла;
КонецПроцедуры
В платформе 1С:Предприятие 8.3 (в версиях до перехода на движок WebKit) элемент Поле HTML-документа в среде Windows использовал встроенный контейнер Internet Explorer (движок MSHTML). При попытке загрузить файл с расширением .pdf движок браузера не выполняет рендеринг документа самостоятельно, а обращается к зарегистрированным в системе ActiveX-компонентам и плагинам просмотра PDF.
Если интеграция настроена корректно, компонент встраивается прямо в контейнер формы 1С. Если же настройки интеграции нарушены или плагин заблокирован, система передает обработку файла внешней ассоциированной программе, что и приводит к появлению отдельного окна Adobe Reader.
Рассмотрим по шагам основные причины сбоя и способы их устранения на рабочем месте пользователя:
Откроем классический браузер Internet Explorer, перейдем в меню «Сервис» (значок шестеренки) → «Настроить надстройки». В списке отображаемых надстроек выберем «Все надстройки» и найдем элемент Adobe PDF Reader. Убедимся, что его состояние установлено в «Включено». Если надстройка отключена, Internet Explorer и контейнер 1С не смогут отображать PDF внутри окна.
Одной из наиболее частых причин принудительного открытия отдельного окна является встроенный механизм изоляции процессов. Откроем Adobe Reader, перейдем в меню «Редактирование» → «Установки» → категория «Основные» (или «Защита (повышенный уровень)»). Найдем параметр «Включить защищенный режим при запуске» (Enable Protected Mode at startup) и снимем этот флаг. После перезапуска программы Adobe Reader перестанет блокировать внедрение компонента в сторонние процессы.
Контейнер 32-разрядного клиента 1С требует наличия 32-битного ActiveX-модуля (AcroPDF.dll). Если на компьютере пользователя установлена 64-битная версия Adobe Reader, 32-битный клиент 1С не сможет загрузить библиотеку и перенаправит открытие во внешнее приложение. Для устранения проблемы необходимо согласовать разрядность платформы 1С и установленного пакета Adobe Reader.
За возможность отображения PDF внутри браузеров отвечает параметр реестра bBrowserIntegration. Проверим его значение в ветках HKEY_CURRENT_USER\Software\Adobe\Acrobat Reader\[Версия]\Originals или HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Adobe\.... Значение параметра типа DWORD должно быть равно 1 (значение 0 полностью запрещает запуск внутри контейнеров).
Поскольку поведение поля HTML с прямой ссылкой на файл сильно зависит от настроек операционной системы и сторонних программ, а современные версии платформы 1С (начиная с 8.3.14) используют собственный встроенный движок на базе WebKit/Chromium (где ActiveX не поддерживается), рассмотрим более надежные варианты реализации просмотра PDF.
Наиболее универсальным методом для любых версий платформы и операционных систем (Windows, Linux, macOS, веб-клиент) является рендеринг документа средствами HTML5 и библиотеки PDF.js. Документ передается в виде строки Base64, а отрисовка выполняется на элементе canvas.
Посмотрим на пример подготовки HTML-кода на сервере:
&НаСервере
Функция ПолучитьHTMLКодСПросмотрщиком(ДвоичныеДанныеPDF)
// Преобразуем двоичные данные документа в строку Base64
СтрокаBase64 = ПолучитьBase64СтрокуИзДвоичныхДанных(ДвоичныеДанныеPDF);
// Формируем HTML со скриптом рендеринга через PDF.js
ТекстHTML =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
" <script src=""https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js""></script>" +
"</head>" +
"<body style=""margin:0; padding:0; overflow:auto;"">" +
" <canvas id=""pdf-canvas""></canvas>" +
" <script>" +
" var pdfData = atob('" + СтрокаBase64 + "');" +
" var loadingTask = pdfjsLib.getDocument({data: pdfData});" +
" loadingTask.promise.then(function(pdf) {" +
" pdf.getPage(1).then(function(page) {" +
" var scale = 1.5;" +
" var viewport = page.getViewport({scale: scale});" +
" var canvas = document.getElementById('pdf-canvas');" +
" var context = canvas.getContext('2d');" +
" canvas.height = viewport.height;" +
" canvas.width = viewport.width;" +
" var renderContext = {canvasContext: context, viewport: viewport};" +
" page.render(renderContext);" +
" });" +
" });" +
" </script>" +
"</body>" +
"</html>";
Возврат ТекстHTML;
КонецФункции
Такой подход полностью изолирует работу формы от установленных в системе ридеров и настроек безопасности браузера.
В современных релизах платформы 1С:Предприятие предусмотрен встроенный объект ДокументPDF, а также специализированный элемент формы Поле PDF-документа. Разберем пример открытия файла с помощью встроенных методов:
&НаКлиенте
Процедура ПросмотретьPDF(ПутьКФайлу)
Документ = Новый ДокументPDF;
Документ.Прочитать(ПутьКФайлу);
// Открытие встроенными средствами платформы 1С
Документ.Показать("Просмотр документа PDF");
КонецПроцедуры
Применение штатных механизмов платформы исключает необходимость интеграции со сторонними утилитами и обеспечивает стабильную работу решения на всех рабочих станциях пользователей.