使用 Javascript 从 div 中的 HTML 生成 pdf

我有以下 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>

我想做的就是打印到 pdf 中找到的任何 ID 为“pdf”的 div。这必须使用 JavaScript 完成。然后应自动下载“pdf”文档,文件名为“foobar.pdf”

我一直在使用 jspdf 来做这个,但它唯一的功能是“text”,它只接受字符串值。我想将 HTML 提交给 jspdf,而不是文本。

回答(12)

7 years ago

**jsPDF 能够使用插件.**为了使其能够打印 HTML,您必须包含某些插件,因此必须执行以下操作:

  • 转到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

如果要忽略某些元素,则必须使用 ID 标记它们,然后可以在 jsPDF 的特殊元素处理程序中忽略该 ID。因此,您的 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>

然后使用以下 JavaScript 代码在 PopUp 中打开创建的 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");

对我来说,这创建了一个漂亮而整洁的 PDF,其中只包括“打印到 pdf”这一行。

请注意,特殊元素处理程序仅处理当前版本中的 ID,这也在GitHub 问题中说明。它指出:

因为匹配是针对节点树中的每个元素完成的,所以我希望尽可能快地完成匹配。在这种情况下,它意味着“只有元素 ID 匹配”元素 ID 仍然以 jQuery 样式“#id”完成,但并不意味着所有 jQuery 选择器都受支持。

因此,用“.ignorePDF”等类选择器替换“#ignorePDF”对我来说不起作用。相反,您将不得不为每个要忽略的元素添加相同的处理程序,如:

var elementHandler = {
  '#ignoreElement': function (element, renderer) {
    return true;
  },
  '#anotherIdToBeIgnored': function (element, renderer) {
    return true;
  }
};

例子开始,还可以选择像'a'或'li'这样的标签。对于大多数用例来说,这可能有点无限制:

我们支持特殊元素处理程序。使用 jQuery-style ID 选择器为 ID 或节点名称注册它们。 (“#iAmID”,“div”,“span”etc.)此时不支持任何其他类型的选择器(复合类)。

一个非常重要的事情是你丢失了所有的风格信息(CSS).幸运的是,jsPDF 可以很好地格式化 h1,h2,h3 等,这对我来说已经足够了.另外,它只会在文本节点中打印文本,这意味着它不会打印 textareas 等的值.例:

<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>

6 years ago

这是一个简单的解决方案。这适用于 me.You 可以使用 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>

6 years ago

您可以使用 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
}

4 years ago

如上所述,您应该使用jsPDFhtml2canvas。我还在 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');
    }
  });
}

3 years ago

如果你需要下载特定页面的 pdf,只需添加这样的按钮

<h4 onclick="window.print();"> Print </h4>

使用 window.print()打印您的所有页面而不仅仅是 div

5 years ago

如果要导出表,可以查看 Shield UI Grid 小部件提供的这个出口样本

这是通过扩展配置来完成的:

...
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" }
            ]
        }
    }
}
...

2 years ago

一种方法是使用 window.print()功能.哪个不需要任何库

****优点

1.No 外部库需要。

2.We 也可以只打印身体的选定部位。

3.No css 冲突和 js 问题。

4.Core html/js 功能

---Simply 添加以下代码

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 代码 -**在 btn 点击时调用 bewlow 函数

$scope.printWindow = function () {
  window.print()
}

注意:在每个 css 对象中使用!important

示例 -

.legend  {
  background: #9DD2E2 !important;
}

6 years ago

我能够让 jsPDF 从 div 打印动态创建的表。

$(document).ready(function() {

        $("#pdfDiv").click(function() {

    var pdf = new jsPDF('p','pt','letter');
    var specialElementHandlers = {
    '#rentalListCan': function (element, renderer) {
        return true;
        }
    };

    pdf.addHTML($('#rentalListCan').first(), function() {
        pdf.save("caravan.pdf");
    });
    });
});

与 Chrome 和 Firefox 配合使用......格式化在 IE 浏览器中全部爆炸。

我还包括这些:

<script src="js/jspdf.js"></script>
    <script src="js/jspdf.plugin.from_html.js"></script>
    <script src="js/jspdf.plugin.addhtml.js"></script>
    <script src="//mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>
    <script src="http://html2canvas.hertzen.com/build/html2canvas.js"></script>
    <script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
    <script type="text/javascript" src="./libs/Blob.js/Blob.js"></script>
    <script type="text/javascript" src="./libs/deflate.js"></script>
    <script type="text/javascript" src="./libs/adler32cs.js/adler32cs.js"></script>

    <script type="text/javascript" src="js/jspdf.plugin.addimage.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.sillysvgrenderer.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.split_text_to_size.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.standard_fonts_metrics.js"></script>

3 years ago

  • 没有依赖性,纯粹的 JS

这为我服务多年了:

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;
}

2 years ago

我使用 jspdf 和 html2canvase 进行 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);

        });

});

4 years ago

要将 div 捕获为 PDF,您可以使用https://grabz.it解决方案。它有一个简单灵活的 JavaScript API,允许您捕获单个 HTML 元素的内容,如 div 或 span

为了实现它,您需要首先获得应用密钥和秘密下载(免费)SDK。

现在举个例子。

假设你有 HTML:

<div id="features">
    <h4>Acme Camera</h4>
    <label>Price</label>$399
<label>Rating</label>4.5 out of 5 </div> <p>Cras ut velit sed purus porttitor aliquam. Nulla tristique magna ac libero tempor, ac vestibulum felisvulput ate. Nam ut velit eget risus porttitor tristique at ac diam. Sed nisi risus, rutrum a metus suscipit, euismod tristique nulla. Etiam venenatis rutrum risus at blandit. In hac habitasse platea dictumst. Suspendisse potenti. Phasellus eget vehicula felis.</p>

要捕获功能 ID 下的内容,您需要:

//add the sdk
<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
//login with your key and secret. 
GrabzIt("KEY", "SECRET").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "format": "pdf"}).Create();
</script>

请注意target: #feature#feature是 CSS 选择器,就像前面的例子一样。现在,当加载页面时,现在将在与脚本标记相同的位置创建图像屏幕截图,脚本标记将包含功能 div 的所有内容,而不包含任何其他内容。

您可以对 div-screenshot 机制进行其他配置和自定义,请查看这里

3 years ago

jsPDF已更新。这是正确的代码

var doc = new jsPDF();
doc.text(20, 20, 'Hello world!');
doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
doc.addPage();
doc.text(20, 20, 'Do you like that?');
doc.save('Test.pdf');