我有以下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,无论在div中找到一个id为“pdf”。这必须使用JavaScript来完成。"pdf"文件会自动下载,文件名为"foobar.pdf"

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


当前回答

如前所述,您应该使用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');
    }
  });
}

其他回答

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

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

现在来看一个例子。

假设你有HTML:

<div id="features">
    <h4>Acme Camera</h4>
    <label>Price</label>$399<br />
    <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>

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

你还可以对div-截图机制进行其他配置和自定义,请在这里查看

没有依赖,纯JS 要添加CSS或图像-不要使用相对url,使用完整的url http://...domain.../path.css左右。它创建单独的HTML文档,没有主要内容的上下文。 您还可以将图像嵌入为base64

多年来,这句话一直为我服务:

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

Of course this will open print dialog and user will have to know she/he can select print to pdf option, to get pdf. There may be printer pre-selected and if user confirms may get this document actually printed. To avoid such situation and to provide PDF without any extras, you need to make PDF file. Probably on the server side. You could have tiny html page with invoice only and convert it to PDF file with headless chrome. It's super easy with puppeteer. No need to install/config chrome, just install npm package puppeteer (managed by chrome team) and run it. Keep in mind this will actually launch real chrome just w/o GUI, so you need to have some RAM & CPU for this. Most servers will be fine with low enough traffic. Here is code sample but this must run on the BACKEND. Nodejs. Also it's slow call, it's resources intensive call. You should run it NOT on api call but e.g. after invoice was created - create pdf for it and store, if pdf was not generated yet, just show message to try again in couple minutes.

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://your-domain.com/path-to-invoice', {
    waitUntil: 'networkidle2',
  });
  await page.pdf({ path: 'invoice-file-path.pdf', format: 'a4' });

  await browser.close();
})();

更多信息请访问:https://pptr.dev/

不满意html2canvas的渲染和缺乏现代CSS3/JS和打印特定的CSS支持pdfMake的过时版本的WebKit…

这是一个理论上的解决方案,它是无头的,可以忠实地渲染页面,支持分页符,页边距,不同的页面大小,并且可以自动化。你甚至可以把WebGl渲染成PDF。

Chrome有一个devtools协议…它有printtoPDF函数 摘录:https://gitlab.com/-/snippets/new 官方20k-SLOC规范:https://github.com/ChromeDevTools/devtools-protocol/blob/master/json/browser_protocol.json 你可以使用节点和https://github.com/GoogleChrome/chrome-launcher运行chrome无头…等待它渲染。 利润

在chrome_devtools协议上执行printToPDF命令:

printToPDF({
  printBackground: false,
  pageWidth: 8.5,
  pageHeight: 11,
  transferMode: "ReturnAsStream" // or ReturnAsBase64
})

这个例子效果很好。

<button onclick="genPDF()">Generate PDF</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script>
    function genPDF() {
        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');
    }
</script>

2022答:

从HTML元素生成PDF并提示保存文件:

import { jsPDF } from "jsPDF"

function generatePDF() {
  const doc = new jsPDF({ unit: 'pt' }) // create jsPDF object
  const pdfElement = document.getElementById('pdf') // HTML element to be converted to PDF

  doc.html(pdfElement, {
    callback: (pdf) => {
      pdf.save('MyPdfFile.pdf')
    },
    margin: 32, // optional: page margin
    // optional: other HTMLOptions
  })
}
<button onclick="generatePDF()">Save PDF</button>

...

不打印预览PDF文件:

doc.html(pdfElement, {
  callback: (pdf) => {
    const myPdfData = pdf.output('datauristring')
  }
})
<embed type="application/pdf" src={myPdfData} />

... 更多的html: https://github.com/parallax/jsPDF/blob/master/types/index.d.ts