Как открыть PDF-файл в ПолеHTMLдокумента в 1С:Предприятие 8.3.14 и новее?

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

С выходом версии платформы 1С:Предприятие 8.3.14 разработчики столкнулись с неприятной проблемой: привычный код для отображения PDF-файлов внутри ПолеHTMLдокумента перестал работать. Вместо отображения документа пользователи начали видеть пустой экран, черный фон или сообщения об ошибках. Выясним причину этой проблемы и подробно разберем несколько эффективных способов ее решения, включая современные встроенные механизмы платформы.

Почему перестал работать старый код?

Для начала проанализируем ситуацию. В более ранних версиях платформы 1С для рендеринга веб-страниц в клиентских приложениях под Windows использовался встроенный движок Internet Explorer (ActiveX). Это позволяло использовать системные плагины (например, Adobe Acrobat Reader), которые автоматически перехватывали отображение файлов с расширением PDF внутри тегов <iframe> или <embed>.

Начиная с версии 8.3.14, фирма «1С» совершила важный технологический шаг и перевела клиентские приложения на современный движок WebKit. Это значительно повысило скорость работы и улучшило поддержку современных веб-стандартов HTML5/CSS3. Однако у этого перехода была и обратная сторона: во встроенном движке WebKit отсутствует встроенный плагин для рендеринга PDF-файлов (в отличие от полноценных браузеров вроде Google Chrome, где для этого используется встроенный компонент PDFium). В результате стандартный код вроде следующего перестал функционировать:


ПолеHTML = "<html><body><iframe width=100% height=100% src=""" + ИмяВременногоФайла + """></iframe></body></html>";

Попытки заменить <iframe> на тег <embed> с указанием типа документа также не приводят к успеху:


ПолеHTML = "<html><body style='margin: 0px'><div><embed width=100% height=100% src=""" + ИмяВременногоФайла + """ type=""application/pdf""></embed></div></body></html>";

Движок WebKit просто не знает, как отобразить этот тип данных без внешнего плагина. Рассмотрим подробнее рабочие варианты решения этой задачи.

Решение 1. Отрисовка PDF через библиотеку PDF.js (с использованием Base64)

Это самый гибкий способ, который позволяет отобразить PDF непосредственно внутри ПолеHTMLдокумента без установки дополнительного программного обеспечения на компьютеры пользователей. Суть метода заключается в использовании бесплатной JavaScript-библиотеки PDF.js от Mozilla, которая рендерит страницы PDF на элементе <canvas>.

Разберем по шагам, как реализовать этот алгоритм в 1С:

  1. Преобразуем двоичные данные нашего PDF-файла в строку формата Base64 на стороне 1С.
  2. Формируем HTML-код, в который внедряем полученную строку Base64.
  3. Подключаем библиотеку PDF.js (через внешние CDN или локальные макеты).
  4. С помощью JavaScript-кода декодируем строку Base64 и отрисовываем страницы документа на холсте.

Посмотрим на пример кода в 1С, реализующий данный подход:


&НаСервере
Функция ПолучитьHTMLКодСPDF(ПутьКФайлуPDF) Экспорт
    
    ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлуPDF);
    СтрокаBase64 = ПолучитьBase64СтрокуИзДвоичныхДанных(ДвоичныеДанные);
    
    // Очищаем строку от возможных переносов строк для корректной передачи в JS
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
    СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ВК, "");
    
    // Формируем HTML-шаблон с подключением библиотеки PDF.js
    HTMLШаблон = 
    "<!DOCTYPE html>
    |<html>
    |<head>
    |  <meta charset=""UTF-8"">
    |  <script src=""https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.min.js""></script>
    |  <style>
    |    body { margin: 0; padding: 0; background-color: #808080; }
    |    .canvas-container { display: flex; flex-direction: column; align-items: center; padding: 10px; }
    |    canvas { box-shadow: 0 4px 8px rgba(0,0,0,0.2); margin-bottom: 10px; max-width: 100%; }
    |  </style>
    |</head>
    |<body>
    |  <div class=""canvas-container"" id=""viewer""></div>
    |
    |  <script>
    |    var pdfData = atob('" + СтрокаBase64 + "');
    |    var pdfjsLib = window['pdfjs-dist/build/pdf'];
    |    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.worker.min.js';
    |
    |    var loadingTask = pdfjsLib.getDocument({data: pdfData});
    |    loadingTask.promise.then(function(pdf) {
    |      var container = document.getElementById('viewer');
    |      
    |      // Последовательно отрисовываем каждую страницу PDF
    |      for (var pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
    |        (function(num) {
    |          pdf.getPage(num).then(function(page) {
    |            var scale = 1.5;
    |            var viewport = page.getViewport({scale: scale});
    |            
    |            var canvas = document.createElement('canvas');
    |            container.appendChild(canvas);
    |            
    |            var context = canvas.getContext('2d');
    |            canvas.height = viewport.height;
    |            canvas.width = viewport.width;
    |            
    |            var renderContext = {
    |              canvasContext: context,
    |              viewport: viewport
    |            };
    |            page.render(renderContext);
    |          });
    |        })(pageNum);
    |      }
    |    }, function (reason) {
    |      console.error(reason);
    |    });
    |  </script>
    |</body>
    |</html>";
    
    Возврат HTMLШаблон;
КонецФункции

Этот способ отлично подходит для базового просмотра документов. Однако помните, что при работе без доступа к интернету библиотеки CDN не загрузятся. В таком случае файлы библиотеки PDF.js необходимо сохранить в макет конфигурации и извлекать их локально.

Решение 2. Использование локального просмотрщика PDF.js (Viewer)

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

Проанализируем этот подход по шагам:

  1. Скачайте официальный дистрибутив PDF.js (версию "Pre-built").
  2. Поместите файлы дистрибутива (включая viewer.html, JS и CSS файлы) в ZIP-архив и добавьте его в конфигурацию как Общий макет с типом "Двоичные данные".
  3. При запуске программы или перед показом документа извлеките этот архив во временную директорию пользователя с помощью объекта ЧтениеZipФайла.
  4. Передайте в ПолеHTMLдокумента путь к распакованному файлу viewer.html, указав путь к целевому PDF-файлу в качестве параметра запроса.

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


&НаКлиенте
Процедура ОткрытьPDFЧерезЛокальныйПросмотрщик(ПутьКФайлуPDF)
    
    ПутьКАрхиву = ПолучитьИмяВременногоФайла("zip");
    МакетАрхива = ПолучитьОбщийМакет("ДистрибутивPDFJS");
    МакетАрхива.Записать(ПутьКАрхиву);
    
    КаталогРаспаковки = КаталогВременныхФайлов() + "pdfjs\";
    СоздатьКаталог(КаталогРаспаковки);
    
    // Распаковка дистрибутива
    Архив = Новый ЧтениеZipФайла(ПутьКАрхиву);
    Архив.ИзвлечьВсе(КаталогРаспаковки, РежимВосстановленияПутейФайловZIP.Восстанавливать);
    Архив.Закрыть();
    
    // Формирование ссылки для WebKit
    ПутьКПросмотрщику = КаталогРаспаковки + "web/viewer.html";
    СсылкаНаПросмотрщик = "file:///" + СтрЗаменить(ПутьКПросмотрщику, "\", "/") 
        + "?file=" + "file:///" + СтрЗаменить(ПутьКФайлуPDF, "\", "/");
        
    // Загрузка в ПолеHTMLдокумента формы
    Элементы.ПолеHTMLПросмотра.Перейти(СсылкаНаПросмотрщик);
    
КонецПроцедуры

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

Решение 3. Конвертация PDF-страниц в изображения

Еще один альтернативный обходной путь — конвертация страниц PDF во временные графические файлы (например, PNG или JPEG) на стороне сервера или клиента. Для этого используются сторонние консольные утилиты, такие как Ghostscript или утилита pdftoppm.

После конвертации полученные картинки страниц можно легко вывести в обычное ПолеКартинки или последовательно загрузить в простое HTML-поле. Этот метод избавляет от необходимости использовать сложные JS-скрипты, но требует наличия установленных утилит конвертации в операционной системе. Для автоматизации этого процесса подойдёт механизм конвертации PDF в графический формат без ручной установки утилит.

Современное решение: нативный механизм для версий 8.3.22 и выше

Если у вас есть возможность обновить версию платформы 1С, настоятельно рекомендуем сделать это. Начиная с версий 8.3.21 и 8.3.22, фирма «1С» решила проблему несовместимости радикально, добавив встроенную поддержку работы с PDF-документами непосредственно во встроенный язык платформы.

Теперь вам не нужно использовать ПолеHTMLдокумента и подключать сторонние библиотеки. Появился новый специализированный объект ДокументPDF.

Давайте посмотрим, как просто теперь выглядит вывод PDF на форму:


&НаКлиенте
Процедура ПоказатьPDFНативно(ПутьКФайлуPDF)
    
    Документ = Новый ДокументPDF();
    Документ.Прочитать(ПутьКФайлуPDF);
    
    // Открытие во встроенном удобном окне просмотра
    Документ.Показать("Просмотр документа: " + ПутьКФайлуPDF);
    
КонецПроцедуры

Также вы можете разместить на управляемой форме реквизит с типом ДокументPDF и связать его с элементом управления Поле PDF документа. Это позволит встроить просмотрщик непосредственно внутрь вашей формы без каких-либо обходных путей и сторонних библиотек. Этот функционал работает одинаково стабильно как в тонком и толстом клиентах под Windows и Linux, так и в веб-клиенте.

← На главную