我有以下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,而不是文本。


当前回答

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

其他回答

没有依赖,纯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/

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

要将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-截图机制进行其他配置和自定义,请在这里查看

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代码在弹出窗口中打开创建的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方式注册它们 ID选择器用于ID或节点名称。(“#iAmID”,“div”,“span”等) 不支持任何其他类型的选择器(class, of 化合物)此时。

要添加的一个非常重要的事情是,您丢失了所有的样式信息(CSS)。幸运的是,jsPDF能够很好地格式化h1、h2、h3等,这对我的目的来说已经足够了。此外,它只打印文本节点中的文本,这意味着它不会打印文本区域等的值。例子:

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

我使用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);

        });
});