簡體   English   中英

從Web應用程序生成設計的PDF報告

[英]Generate a designed PDF report from a web application

我想從Web應用程序生成PDF報告。 PDF應包含圖表(餅圖,條形圖),表格,不同的字體和顏色。

應用程序的服務器端是Java,客戶端是AngularJS(當然還有CSS3和HTML)。

兩個主要選項:

  • 客戶端將一些參數傳遞給服務器,服務器將使用Java包生成PDF報告。 然后,報告將作為下載文件發送回客戶端。
  • 客戶端將使用將HTML和CSS轉換為PDF的JS包生成報告。

在Java世界中,我發現了iText和JFreeChart之類的東西 ,例如here 這里的問題是,圖表的設計在示例中看起來很糟糕,我不知道是否可以將其更改為由我擁有的樣式指南(可以通過CSS輕松完成的設計)進行設計。

在JS世界中,我發現了html2canvas和pdfMake,例如here 這里的問題是我不確定從HTML到canvas再到PDF的轉換在Angular應用程序中是否能正常工作。 而且我不確定它是否可以轉換復雜的DOM元素,例如svg中的圖表或canvas元素。

您對這些軟件包有經驗嗎? 您是否知道針對此任務,客戶端或服務器的其他推薦軟件包?

想要分享我的解決方案...我選擇了客戶端解決方案。

我從jsPDF開始,但是有一些問題。 例如,很難用我想要的樣式轉換表。

我選擇pdfMake為PDF生成, html2canvas采取復雜設計的部件的屏幕截圖,並canvg為d3js圖表(SVG圖表)轉化為畫布(pdfMake可以為圖像添加畫布文檔)。

我編寫了一個函數,該函數獲取要轉換為PDF的部件的HTML根的CSS類(請記住它是單頁應用程序),並且還獲取有關哪個HTML節點的元數據(同樣,通過其CSS類)應該添加到PDF(節點是什么類型-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);
  });

這通常是解決方案。 希望它會幫助某人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM