在 Angular 6 中将 HTML 转换为 PDF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52576473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 15:44:49  来源:igfitidea点击:

Convert HTML to PDF in Angular 6

htmlangularpdfangular6jspdf

提问by Vivekanand P V

I have a component (Angular 6) which is an aggregation of several components. This produces a long HTML (I am using Bootstrap 4). Now I want to convert this HTML to PDF. I have searched far and wide and found many solutions that work on jsPDF. The requirement is to produce a crisp layout as it appears in the HTML (so that users can select, copy, etc). But the solutions I found either try to add lines of text manually, which is impossible in my scenario; or they convert (rasterize?) the HTML to image format. Also, I want to preserve the formatting and fonts and styling of my HTML.

我有一个组件(Angular 6),它是几个组件的聚合。这会产生一个很长的 HTML(我使用的是 Bootstrap 4)。现在我想将此 HTML 转换为 PDF。我进行了广泛的搜索,发现了许多适用于 jsPDF 的解决方案。要求是生成在 HTML 中显示的清晰布局(以便用户可以选择、复制等)。但是我找到的解决方案要么尝试手动添加文本行,这在我的场景中是不可能的;或者他们将 HTML 转换(光栅化?)到图像格式。另外,我想保留 HTML 的格式、字体和样式。

So far I have tried: thisand this.

到目前为止,我已经尝试过:thisthis

回答by Anirudh

Best possible solution I could come up with till now.

到目前为止我能想出的最佳解决方案。

You would have to install the below packages from npm

您必须从 npm 安装以下软件包

html2canvas

html2canvas

jspdf

jspdf

import * as jsPDF from 'jspdf';
import html2canvas from 'html2canvas';

htmltoPDF()
{
    // parentdiv is the html element which has to be converted to PDF
    html2canvas(document.querySelector("#parentdiv")).then(canvas => {

      var pdf = new jsPDF('p', 'pt', [canvas.width, canvas.height]);

      var imgData  = canvas.toDataURL("image/jpeg", 1.0);
      pdf.addImage(imgData,0,0,canvas.width, canvas.height);
      pdf.save('converteddoc.pdf');

  });

}

UPDATE:

更新:

Came up with another solution. I wasn't able to break it down into A4 size pages, but I was able to make a single pdf file.

想出了另一个解决方案。我无法将其分解为 A4 大小的页面,但我能够制作一个 pdf 文件。

Packages:

套餐:

dom-to-image

dom-to-image

jspdf

jspdf

import domtoimage from 'dom-to-image';
import * as jsPDF from 'jspdf';



            downloadPDF()
            {

              var node = document.getElementById('parentdiv');

              var img;
              var filename;
              var newImage;


              domtoimage.toPng(node, { bgcolor: '#fff' })

                .then(function(dataUrl) {

                  img = new Image();
                  img.src = dataUrl;
                  newImage = img.src;

                  img.onload = function(){

                  var pdfWidth = img.width;
                  var pdfHeight = img.height;

                    // FileSaver.saveAs(dataUrl, 'my-pdfimage.png'); // Save as Image

                    var doc;

                    if(pdfWidth > pdfHeight)
                    {
                      doc = new jsPDF('l', 'px', [pdfWidth , pdfHeight]);
                    }
                    else
                    {
                      doc = new jsPDF('p', 'px', [pdfWidth , pdfHeight]);
                    }


                    var width = doc.internal.pageSize.getWidth();
                    var height = doc.internal.pageSize.getHeight();


                    doc.addImage(newImage, 'PNG',  10, 10, width, height);
                    filename = 'mypdf_' + '.pdf';
                    doc.save(filename);

                  };


                })
                .catch(function(error) {

                 // Error Handling

                });



            }

回答by MapLion

With some effort, the best solution my team and I came up with for our own Angular HTML to PDF problems involved sending the raw HTML to our Java API and then utilizing wkhtmltopdf (https://github.com/wkhtmltopdf/wkhtmltopdf) with the Java wrapper (https://github.com/jhonnymertz/java-wkhtmltopdf-wrapper). Overcoming a few gotchas (like making sure the server has the correctly installed fonts; everything is properly encoded; figuring out page breaks and making them work), we were able to reproduce our page exactly and use our Angular HTML as the universal template (which changes based on different scenarios). It is not an easy road, but it is one that produces great results in an enterprise-level production environment once you get it figured out.

经过一些努力,我和我的团队为我们自己的 Angular HTML to PDF 问题提出了最好的解决方案,包括将原始 HTML 发送到我们的 Java API,然后使用 wkhtmltopdf ( https://github.com/wkhtmltopdf/wkhtmltopdf) 和Java 包装器(https://github.com/jhonnymertz/java-wkhtmltopdf-wrapper)。克服了一些问题(比如确保服务器安装了正确的字体;一切都被正确编码;找出分页符并使它们工作),我们能够准确地重现我们的页面并使用我们的 Angular HTML 作为通用模板(它根据不同场景变化)。这不是一条容易的道路,但一旦你弄清楚它,它就会在企业级生产环境中产生很好的结果。

It should be noted that we also tried jspdf (and other libraries) and came to similar conclusions as yourself: they just didn't do what we needed them to do. Hopefully this helps.

应该注意的是,我们也尝试了 jspdf(和其他库)并得出了与您类似的结论:他们只是没有做我们需要他们做的事情。希望这会有所帮助。

回答by Basil Mohammed

The following code was used and worked for my project

以下代码已用于并适用于我的项目

Step 1 : Run following commands to install npm packages

第 1 步:运行以下命令安装 npm 包

> npm install jspdf
> npm install html2canvas

Step 2: Import installed packages in app.components.ts. I haven't imported those packages in constructor()

第二步:在 app.components.ts 中导入已安装的包。我没有在构造函数()中导入这些包

> import * as jspdf from 'jspdf';
> import html2canvas from 'html2canvas';

Step 3: Give an id for the HTML div that has to be exported as PDF. Add a button that activates the function too.

第 3 步:为必须导出为 PDF 的 HTML div 提供一个 id。添加一个按钮来激活该功能。

<div id="MyDIv" style="margin-left: 45px;" class="main-container">

</div>
<div class="icon_image " title="Share As PDF" (click)="exportAsPDF('MyDIv');"><img src="assets/img/pdf.png"></div>

Step 4 : Write the code for generating PDF as follows

第四步:编写生成PDF的代码如下

exportAsPDF()
  {
    let data = document.getElementById('MyDIv');  
    html2canvas(data).then(canvas => {
      const contentDataURL = canvas.toDataURL('image/png')  
      let pdf = new jspdf('l', 'cm', 'a4'); //Generates PDF in landscape mode
      // let pdf = new jspdf('p', 'cm', 'a4'); Generates PDF in portrait mode
      pdf.addImage(contentDataURL, 'PNG', 0, 0, 29.7, 21.0);  
      pdf.save('Filename.pdf');   
    }); 
  }

回答by Jasim Jas

Step 1: Install required packages

第 1 步:安装所需的软件包

npm install jspdf jspdf-autotable

Step 2: Import the installed packages to use

第二步:导入已安装的包使用

 import jsPDF from 'jspdf';
 import 'jspdf-autotable';

Step 3: If your data has images, convert images to Base64

第 3 步:如果您的数据有图像,请将图像转换为 Base64

tabledata = [{
    img: 'https://i.picsum.photos/id/258/536/354.jpg',
    name: 'Joseph',
    domain: 'Angular 9'
  },
  {
    img: 'https://i.picsum.photos/id/258/536/354.jpg',
    name: 'Vani',
    domain: 'Angular 8'
  }, {
    img: 'https://i.picsum.photos/id/258/536/354.jpg',
    name: 'Raj',
    domain: 'React.js'
  },
];

The above is data with images converted to base64. The convert function looks like:

以上是图片转base64后的数据。转换函数如下所示:

convertImagetoBase64(url, callback) {
    const xhr = new XMLHttpRequest();
    xhr.onload = () => {
      const reader = new FileReader();
      reader.onloadend = () => {
        callback(reader.result);
      };
      reader.readAsDataURL(xhr.response);
    };
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.send();
}

Let's convert the image URL to base64 before we bind to the table in HTML.

在绑定到 HTML 表格之前,让我们将图像 URL 转换为 base64。

this.tabledata.forEach(elem => {
  this.convertImagetoBase64(elem.img, (b64Img) => {
    elem.img = b64Img;
});

Now bind the data to the table. If you don't want to display the table in the front end, just style to display none as in the below code:

现在将数据绑定到表。如果您不想在前端显示表格,只需将样式设置为不显示,如下面的代码所示:

<table id="imgTable" style=”display:none”>
<thead>
    <tr><th>Name</th>
    <th>Domain</th>
    <th>Image</th>
    </tr>
</thead>
<tbody>
    <tr *ngFor="let data of tabledata">
        <td>{{data.name}}</td>
        <td>{{data.domain}}</td>
        <td><img src="{{data.img}}" width="100" height="100" /></td>
    </tr>

</tbody>
</table>
<button (click)="generatePdf()">Generate Pdf</button>

The Generate Pdf function looks like:

生成 Pdf 函数如下所示:

app.component.ts

app.component.ts

generatePdf(){
 doc.autoTable({
  html: '#imgTable',
  bodyStyles: { minCellHeight: 20 },
  theme: 'grid',
  styles: { valign: 'middle', overflow: 'linebreak', halign: 'center', minCellHeight: 21 },
  pageBreak: 'avoid',
  columnStyles: {
    2: { cellWidth: 22, minCellHeight: 22 },
  },
  headStyles: { fillColor: '#f2f2f2', textColor: '#000', fontStyle: 'bold', lineWidth: 0.5, lineColor: '#ccc' },
  didDrawCell: (data) => {
    if (data.column.index === 2 && data.cell.section === 'body') {
      const td = data.cell.raw;
      const img = td.getElementsByTagName('img')[0];
      // let dim = data.cell.height - data.cell.padding('vertical');
      // let textPos = data.cell.textPos;
      doc.addImage(img.src, data.cell.x + 1, data.cell.y + 1, 19, 19);

    }
  }
});
 doc.save('yourpdfname.pdf');
}

Example pdf generation looks like:

pdf 生成示例如下所示:

For more Pdf format without table visit helperscript.com

有关没有表格的更多 Pdf 格式,请访问 helperscript.com

回答by dasunse

Try to use a backend service for this such as Thymeleafor itextpdfwith Spring Boot.

尝试为此使用后端服务,例如带有 Spring Boot 的Thymeleafitextpdf

回答by Vaishnavi

Firstly install the following: 1) npm install jspdf 2) npm install html2canvas

首先安装以下内容:1) npm install jspdf 2) npm install html2canvas

Later import and use the following code

稍后导入并使用以下代码

 public captureScreen() {
      const data = document.getElementById('invoice');
      html2canvas(data).then(canvas => {
      const imgWidth = 208;
      const pageHeight = 295;
      const imgHeight = canvas.height * imgWidth / canvas.width;
      const heightLeft = imgHeight;
      const contentDataURL = canvas.toDataURL('image/png');
      const pdf = new jspdf('p', 'mm', 'a4'); 
      const position = 0;
      pdf.addImage(contentDataURL, 'PNG', 0, position, imgWidth, imgHeight);
      pdf.save('invoice.pdf'); 
      });
      }