在 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
Convert HTML to PDF in Angular 6
提问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 的格式、字体和样式。
回答by Anirudh
Best possible solution I could come up with till now.
到目前为止我能想出的最佳解决方案。
You would have to install the below packages from npm
您必须从 npm 安装以下软件包
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:
套餐:
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
回答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');
});
}