javascript 使用Javascript从div中的HTML生成pdf
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18191893/
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
Generate pdf from HTML in div using Javascript
提问by John Crawford
I have the following html code:
我有以下 html 代码:
<!DOCTYPE html>
<html>
<body>
<p>don't print this to pdf</p>
<div id="pdf">
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
All I want to do is to print to pdf whatever is found in the div with an id of "pdf". This must be done using JavaScript. The "pdf" document should then be automatically downloaded with a filename of "foobar.pdf"
我想要做的就是将 div 中的任何内容打印为 pdf,id 为“pdf”。这必须使用 JavaScript 来完成。然后应自动下载“pdf”文档,文件名为“foobar.pdf”
I've been using jspdf to do this, but the only function it has is "text" which accepts only string values. I want to submit HTML to jspdf, not text.
我一直在使用 jspdf 来做到这一点,但它唯一的功能是“文本”,它只接受字符串值。我想将 HTML 提交给 jspdf,而不是文本。
采纳答案by snrlx
jsPDF is able to use plugins.In order to enable it to print HTML, you have to include certain plugins and therefore have to do the following:
jsPDF 能够使用插件。为了使其能够打印 HTML,您必须包含某些插件,因此必须执行以下操作:
- Go to https://github.com/MrRio/jsPDFand download the latest Version.
- Include the following Scripts in your project:
- jspdf.js
- jspdf.plugin.from_html.js
- jspdf.plugin.split_text_to_size.js
- jspdf.plugin.standard_fonts_metrics.js
- 去https://github.com/MrRio/jsPDF下载最新版本。
- 在您的项目中包含以下脚本:
- jspdf.js
- jspdf.plugin.from_html.js
- jspdf.plugin.split_text_to_size.js
- jspdf.plugin.standard_fonts_metrics.js
If you want to ignore certain elements, you have to mark them with an ID, which you can then ignore in a special element handler of jsPDF. Therefore your HTML should look like this:
如果你想忽略某些元素,你必须用一个 ID 标记它们,然后你可以在 jsPDF 的特殊元素处理程序中忽略它。因此,您的 HTML 应如下所示:
<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
Then you use the following JavaScript code to open the created PDF in a PopUp:
然后使用以下 JavaScript 代码在弹出窗口中打开创建的 PDF:
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
For me this created a nice and tidy PDF that only included the line 'print this to pdf'.
对我来说,这创建了一个漂亮整洁的 PDF,其中仅包含“将其打印为 pdf”这一行。
Please note that the special element handlers only deal with IDs in the current version, which is also stated in a GitHub Issue. It states:
请注意,特殊元素处理程序仅处理当前版本中的 ID,这也在GitHub 问题 中说明。它指出:
Because the matching is done against every element in the node tree, my desire was to make it as fast as possible. In that case, it meant "Only element IDs are matched" The element IDs are still done in jQuery style "#id", but it does not mean that all jQuery selectors are supported.
因为匹配是针对节点树中的每个元素进行的,所以我的愿望是尽可能快地进行匹配。在那种情况下,这意味着“仅匹配元素 ID” 元素 ID 仍然以 jQuery 样式“#id”完成,但这并不意味着支持所有 jQuery 选择器。
Therefore replacing '#ignorePDF' with class selectors like '.ignorePDF' did not work for me. Instead you will have to add the same handler for each and every element, which you want to ignore like:
因此,用“.ignorePDF”之类的类选择器替换“#ignorePDF”对我不起作用。相反,您必须为每个要忽略的元素添加相同的处理程序,例如:
var elementHandler = {
'#ignoreElement': function (element, renderer) {
return true;
},
'#anotherIdToBeIgnored': function (element, renderer) {
return true;
}
};
From the examplesit is also stated that it is possible to select tags like 'a' or 'li'. That might be a little bit to unrestrictive for the most usecases though:
从示例中还说明可以选择像“a”或“li”这样的标签。不过,对于大多数用例来说,这可能有点不受限制:
We support special element handlers. Register them with jQuery-style ID selector for either ID or node name. ("#iAmID", "div", "span" etc.) There is no support for any other type of selectors (class, of compound) at this time.
我们支持特殊的元素处理程序。使用 jQuery 样式的 ID 选择器为 ID 或节点名称注册它们。(“#iAmID”、“div”、“span”等)目前不支持任何其他类型的选择器(类、复合)。
One very important thing to add is that you lose all your style information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3 etc., which was enough for my purposes. Additionally it will only print text within text nodes, which means that it will not print the values of textareas and the like. Example:
要添加的一件非常重要的事情是您丢失了所有样式信息 (CSS)。幸运的是 jsPDF 能够很好地格式化 h1、h2、h3 等,这对我的目的来说已经足够了。此外,它只会打印文本节点内的文本,这意味着它不会打印 textarea 等的值。例子:
<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>
回答by vaibhav kulkarni
This is the simple solution. This works for me.You can use the javascript print concept and simple save this as pdf.
这是简单的解决方案。这对我有用。您可以使用 javascript 打印概念并简单地将其另存为 pdf。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$("#btnPrint").live("click", function () {
var divContents = $("#dvContainer").html();
var printWindow = window.open('', '', 'height=400,width=800');
printWindow.document.write('<html><head><title>DIV Contents</title>');
printWindow.document.write('</head><body >');
printWindow.document.write(divContents);
printWindow.document.write('</body></html>');
printWindow.document.close();
printWindow.print();
});
</script>
</head>
<body>
<form id="form1">
<div id="dvContainer">
This content needs to be printed.
</div>
<input type="button" value="Print Div Contents" id="btnPrint" />
</form>
</body>
</html>
回答by Marco
You can use autoPrint() and set output to 'dataurlnewwindow' like this:
您可以使用 autoPrint() 并将输出设置为“dataurlnewwindow”,如下所示:
function printPDF() {
var printDoc = new jsPDF();
printDoc.fromHTML($('#pdf').get(0), 10, 10, {'width': 180});
printDoc.autoPrint();
printDoc.output("dataurlnewwindow"); // this opens a new popup, after this the PDF opens the print window view but there are browser inconsistencies with how this is handled
}
回答by Wael Mahmoud
if you need to downloadable pdf of a specific page just add button like this
如果您需要下载特定页面的 pdf,只需添加这样的按钮
<h4 onclick="window.print();"> Print </h4>
use window.print() to print your all page not just a div
使用 window.print() 打印您的所有页面而不仅仅是一个 div
回答by BaptWaels
As mentioned, you should use jsPDFand html2canvas. I've also found a function inside issues of jsPDF which splits automatically your pdf into multiple pages (sources)
如前所述,您应该使用jsPDF和html2canvas。我还在 jsPDF 问题中找到了一个函数,它会自动将您的 pdf 分成多个页面(来源)
function makePDF() {
var quotes = document.getElementById('container-fluid');
html2canvas(quotes, {
onrendered: function(canvas) {
//! MAKE YOUR PDF
var pdf = new jsPDF('p', 'pt', 'letter');
for (var i = 0; i <= quotes.clientHeight/980; i++) {
//! This is all just html2canvas stuff
var srcImg = canvas;
var sX = 0;
var sY = 980*i; // start 980 pixels down for every new page
var sWidth = 900;
var sHeight = 980;
var dX = 0;
var dY = 0;
var dWidth = 900;
var dHeight = 980;
window.onePageCanvas = document.createElement("canvas");
onePageCanvas.setAttribute('width', 900);
onePageCanvas.setAttribute('height', 980);
var ctx = onePageCanvas.getContext('2d');
// details on this usage of this function:
// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);
// document.body.appendChild(canvas);
var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);
var width = onePageCanvas.width;
var height = onePageCanvas.clientHeight;
//! If we're on anything other than the first page,
// add another page
if (i > 0) {
pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
}
//! now we declare that we're working on that page
pdf.setPage(i+1);
//! now we add content to that page!
pdf.addImage(canvasDataURL, 'PNG', 20, 40, (width*.62), (height*.62));
}
//! after the for loop is finished running, we save the pdf.
pdf.save('test.pdf');
}
});
}
回答by Rohit Parte
One way is to use window.print() function. Which does not require any library
一种方法是使用 window.print() 函数。哪个不需要任何库
Pros
优点
1.No external library require.
1.不需要外部库。
2.We can print only selected parts of body also.
2.我们也可以只打印身体的选定部分。
3.No css conflicts and js issues.
3.没有css冲突和js问题。
4.Core html/js functionality
4.核心html/js功能
---Simply add below code
---只需添加以下代码
CSSto
CSS到
@media print {
body * {
visibility: hidden; // part to hide at the time of print
-webkit-print-color-adjust: exact !important; // not necessary use
if colors not visible
}
#printBtn {
visibility: hidden !important; // To hide
}
#page-wrapper * {
visibility: visible; // Print only required part
text-align: left;
-webkit-print-color-adjust: exact !important;
}
}
JS code -Call bewlow function on btn click
JS 代码 -在 btn 单击上调用 bewlow 函数
$scope.printWindow = function () {
window.print()
}
Note: Use !important in every css object
注意:在每个 css 对象中使用 !important
Example -
例子 -
.legend {
background: #9DD2E2 !important;
}
回答by ghazaleh javaheri
i use jspdfand html2canvasfor css rendering and i export content of specific div as this is my code
我使用jspdf和html2canvas进行 css 渲染,并导出特定 div 的内容,因为这是我的代码
$(document).ready(function () {
let btn=$('#c-oreder-preview');
btn.text('download');
btn.on('click',()=> {
$('#c-invoice').modal('show');
setTimeout(function () {
html2canvas(document.querySelector("#c-print")).then(canvas => {
//$("#previewBeforeDownload").html(canvas);
var imgData = canvas.toDataURL("image/jpeg",1);
var pdf = new jsPDF("p", "mm", "a4");
var pageWidth = pdf.internal.pageSize.getWidth();
var pageHeight = pdf.internal.pageSize.getHeight();
var imageWidth = canvas.width;
var imageHeight = canvas.height;
var ratio = imageWidth/imageHeight >= pageWidth/pageHeight ? pageWidth/imageWidth : pageHeight/imageHeight;
//pdf = new jsPDF(this.state.orientation, undefined, format);
pdf.addImage(imgData, 'JPEG', 0, 0, imageWidth * ratio, imageHeight * ratio);
pdf.save("invoice.pdf");
//$("#previewBeforeDownload").hide();
$('#c-invoice').modal('hide');
});
},500);
});
});
回答by Lukas Liesis
- No depenencies, pure JS
- To add CSS or images - do not use relative URLs, use full URLs
http://...domain.../path.cssor so. It creates separate HTML document and it has no context of main thing. - you can also embed images as base64
- 无依赖,纯JS
- 要添加 CSS 或图像 - 不要使用相对 URL,使用完整 URL 等
http://...domain.../path.css。它创建单独的 HTML 文档,并且没有主要内容的上下文。 - 您还可以将图像嵌入为 base64
This served me for years now:
这为我服务了多年:
export default function printDiv({divId, title}) {
let mywindow = window.open('', 'PRINT', 'height=650,width=900,top=100,left=150');
mywindow.document.write(`<html><head><title>${title}</title>`);
mywindow.document.write('</head><body >');
mywindow.document.write(document.getElementById(divId).innerHTML);
mywindow.document.write('</body></html>');
mywindow.document.close(); // necessary for IE >= 10
mywindow.focus(); // necessary for IE >= 10*/
mywindow.print();
mywindow.close();
return true;
}
回答by ilmiacs
Use pdfMake.jsand this Gist.
(I found the Gist herealong with a link to the package html-to-pdfmake, which I end up not using for now.)
(我在这里找到了 Gist以及指向html-to-pdfmake包的链接,我现在最终没有使用它。)
After npm install pdfmakeand saving the Gist in htmlToPdf.jsI use it like this:
在npm install pdfmake保存 Gist 之后,htmlToPdf.js我像这样使用它:
const pdfMakeX = require('pdfmake/build/pdfmake.js');
const pdfFontsX = require('pdfmake-unicode/dist/pdfmake-unicode.js');
pdfMakeX.vfs = pdfFontsX.pdfMake.vfs;
import * as pdfMake from 'pdfmake/build/pdfmake';
import htmlToPdf from './htmlToPdf.js';
var docDef = htmlToPdf(`<b>Sample</b>`);
pdfMake.createPdf({content:docDef}).download('sample.pdf');
Remarks:
评论:
- My use case is to create the relevant html from a markdown document (with markdown-it) and subsequently generating the pdf, and uploading its binary content (which I can get with
pdfMake'sgetBuffer()function), all from the browser. The generated pdf turns out to be nicer for this kind of html than with other solutions I have tried. - I am dissatisfied with the results I got from
jsPDF.fromHTML()suggested in the accepted answer, as that solution gets easily confused by special characters in my HTML that apparently are interpreted as a sort of markup and totally mess up the resulting PDF. - Using canvas based solutions (like the deprecated
jsPDF.from_html()function, not to be confused with the one from the accepted answer) is not an option for me since I want the text in the generated PDF to be pasteable, whereas canvas based solutions generate bitmap based PDFs. - Direct markdown to pdf converters like md-to-pdfare server side only and would not work for me.
- Using the printing functionality of the browser would not work for me as I do not want to display the generated PDF but upload its binary content.
- 我的用例是从 Markdown 文档(使用markdown-it)创建相关的 html ,然后生成 pdf,并上传其二进制内容(我可以使用
pdfMake的getBuffer()功能获得),所有这些都来自浏览器。与我尝试过的其他解决方案相比,生成的 pdf 对这种 html 来说更好。 - 我对
jsPDF.fromHTML()接受的答案中建议的结果不满意,因为该解决方案很容易被我的 HTML 中的特殊字符混淆,这些特殊字符显然被解释为一种标记并完全弄乱了生成的 PDF。 - 使用基于画布的解决方案(如已弃用的
jsPDF.from_html()功能,不要与接受的答案混淆)对我来说不是一个选择,因为我希望生成的 PDF 中的文本是可粘贴的,而基于画布的解决方案生成基于位图的 PDF。 - 直接降价到 pdf 转换器(如md-to-pdf)仅是服务器端,对我不起作用。
- 使用浏览器的打印功能对我不起作用,因为我不想显示生成的 PDF 而是上传其二进制内容。
回答by Vladimir Georgiev
If you want to export a table, you can take a look at this export sampleprovided by the Shield UI Grid widget.
如果要导出表,可以查看Shield UI Grid 小部件提供的此导出示例。
It is done by extending the configuration like this:
它是通过像这样扩展配置来完成的:
...
exportOptions: {
proxy: "/filesaver/save",
pdf: {
fileName: "shieldui-export",
author: "John Smith",
dataSource: {
data: gridData
},
readDataSource: true,
header: {
cells: [
{ field: "id", title: "ID", width: 50 },
{ field: "name", title: "Person Name", width: 100 },
{ field: "company", title: "Company Name", width: 100 },
{ field: "email", title: "Email Address" }
]
}
}
}
...

