Создать разработанный PDF-отчет из веб-приложения

0

Я хочу создать отчет в формате PDF из веб-приложения. PDF должен содержать диаграммы (pie, bar), таблицы, разные шрифты и цвета.

Серверная сторона приложения - Java, клиентская сторона - AngularJS (и, конечно, CSS3 и HTML).

Два основных варианта:

  • Клиентская сторона передаст некоторые параметры серверу, и сервер будет генерировать отчет в формате PDF с использованием пакета Java. Затем отчет будет отправлен обратно клиенту в виде загруженного файла.
  • Клиент будет генерировать отчет, используя JS-пакет, который преобразует HTML и CSS в PDF.

В мире Java я нашел, например, iText и JFreeChart, как здесь. Проблема здесь в том, что дизайн диаграмм выглядит плохо в этом примере, и я не знаю, можно ли его изменить, чтобы быть разработанным стилем-руководством, которое у меня есть (дизайн, который можно легко сделать с помощью CSS).

В мире JS я нашел, например, html2canvas и pdfMake, как здесь. Проблема здесь в том, что я не уверен, что преобразование из HTML в холст, а затем в PDF будет работать в угловом приложении. И я не уверен, что он преобразует хорошо сложные элементы DOM, такие как диаграммы в svg или canvas.

Есть ли у вас опыт работы с этими пакетами? Знаете ли вы другие рекомендуемые пакеты для этой задачи, клиента или сервера?

  • 0
    Может быть, посмотрите на cloudformatter.com/CSS2Pdf, который поддерживает прямой SVG в PDF, а не через canvas.
  • 0
    Спасибо @KevinBrown. Я не могу использовать это решение, потому что это облачное решение. Вы отправляете им запрос POST, и они возвращают PDF. Наше приложение также должно работать без подключения к Интернету (из-за проблем безопасности в крупных организациях), поэтому нам нужно решение, которое создает PDF самостоятельно.
Теги:
pdf

1 ответ

0

Хотите поделиться своим решением... Я выбрал клиентское решение.

Я начал с jsPDF, но имел некоторые проблемы. Например, было сложно преобразовать таблицы со стилем, который я хочу.

Я выбрал pdfMake для генерации PDF, html2canvas для создания скриншотов сложных компонентов и canvg для преобразования диаграмм d3js (svg-диаграммы) в холст (pdfMake может добавлять холст в качестве изображения в документ).

Я написал функцию, которая получает класс CSS корня HTML части, которую я хочу преобразовать в PDF (помните, что это одностраничное приложение), а также получает метаданные, из которых узлы HTML (опять же, по их классам CSS) должен быть добавлен в PDF (и какой тип является node-table/text/image/svg).

Затем, пройдя DOM, я прошел через элементы, которые я хочу добавить в PDF, и обрабатывал каждый по типу. Часть кода (перемещение и случай переключения по типу):

$(htmlRootSelector).contents().each(function processNodes(index, element) {
    var classMeta = getMetaByClass(element.className);

    if (!classMeta) {
      $(element).contents().each(processNodes);
      return;
    }

    var pdfObj = {};
    pdfObj.width = classMeta.width || angular.undefined;
    pdfObj.height = classMeta.height || angular.undefined;
    pdfObj.style = classMeta.style || angular.undefined;
    pdfObj.pageBreak = classMeta.pageBreak || angular.undefined;

    switch (classMeta.type) {
    case 'text':
      pdfObj.text = element.innerText;
      pdfDefinition.content.push(pdfObj);
      break;
    case 'table':
      var tableArray = [];
      var headerArray = [];
      var headers = $(element).find('th');
      var rows = $(element).find('tr');
      $.each(headers, function (i, header) {
        headerArray.push({text: header.innerHTML, style: classMeta.style + '-header'});
      });
      tableArray.push(headerArray);

      $.each(rows, function (i, row) {
        var rowArray = [];
        var cells = $(row).find('td');

        if (cells.length) {
          $.each(cells, function (j, cell) {
            rowArray.push(i % 2 === 1 ? {text: cell.innerText, style: classMeta.style + '-odd-row'} : cell.innerText);
          });

          tableArray.push(rowArray);
        }
      });

      pdfObj.table = {
        widths: $.map(headers, function (d, i) {
          return i === 0 ? 80 : '*';
        }),
        body: tableArray
      };
      pdfDefinition.content.push(pdfObj);
      break;
    case 'image':
      html2CanvasCount++;
      htmlToCanvas(element, pdfObj);
      pdfDefinition.content.push(pdfObj);
      break;
    case 'svg':
      svgToCanvas(element, pdfObj);
      pdfDefinition.content.push(pdfObj);
      break;
    default:
      break;
    }

    $(element).contents().each(processNodes);
  });

Это решение в целом. Надеюсь, это поможет кому-то.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню