简体   繁体   English

使用html-pdf包动态生成pdf

[英]dynamically generate pdf with the html-pdf package

I am using the npm package html-pdf 我正在使用npm包html-pdf

I was trying to dynamically generate invoices. 我试图动态生成发票。 Eventually it creates PDF files but instead of saving values to the PDF it saves ejs code. 最终,它创建了PDF文件,但没有保存值到PDF,而是保存了ejs代码。 Anyone knows what went wrong? 有人知道出了什么问题吗?

You can check the screenshot below of the PDF output with ejs variables: 您可以使用ejs变量检查以下PDF输出的屏幕截图:

https://i.stack.imgur.com/LPjN7.png https://i.stack.imgur.com/LPjN7.png

Now let me explain my node app: 现在让我解释一下我的节点应用程序:

I am using two ejs pages. 我正在使用两个ejs页面。 One is home.ejs from where we post input values which need to be filled in the PDF. 其中之一是home.ejs ,我们从此处发布需要填写在PDF中的输入值。 Second page is crm.ejs where my invoice template is. 第二页是crm.ejs ,这是我的发票模板。 In crm.ejs I am using window.onload function so when everything is loaded to my crm.ejs template . crm.ejs我使用window.onload函数,因此当所有内容都加载到我的crm.ejs模板中时。 Then it will generate PDF. 然后它将生成PDF。 But still it only save ejs variables. 但是仍然只保存ejs变量。

Now here is the code 现在这是代码

app.js app.js

var express = require("express");
var app = express();
var webshot = require('webshot');
var fs = require('fs');
var pdf = require('html-pdf');
var html = fs.readFileSync('views/crm.ejs', 'utf8');
var options = { format: 'a4' };
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({extended:true}));

app.locals.pdf = require("html-pdf");
app.locals.html = fs.readFileSync('views/crm.ejs', 'utf8');
app.locals.options =  { format: 'a4' };
app.locals.fs = require("fs");
app.use(express.static("public"));

app.get("/",function(req,res){
    res.render("home.ejs");
});

app.post("/crm",function(req,res){
    // res.render("crm.ejs");
    console.log(req.body);
    var details = req.body;
    res.render("crm.ejs",{details:details});
});

app.listen(process.env.PORT,process.env.IP,function(){
    console.log("Server started successfully!!");
}); 

home.ejs: home.ejs:

 <form action="/crm" method="post">
    <label>First Name</label>
    <input type="text" name="fname"><br />

    <label>Last Name</label>
    <input type="text" name="lname"><br />

    <label>Email</label>
    <input type="text" name="email"><br />

    <label>Phone number</label>
    <input type="text" name="phone"><br />

    <label>Address</label>
    <textarea name="address"></textarea><br />

    <button>Save</button>

</form>

crm.ejs: crm.ejs:

<html>
<head>
<title>BillBook</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
    #billbook{
       height:845px;
        width:595px;
        background-repeat: no-repeat;
        background-size: 595px 845px;
        border:1px solid red;
        /*margin:0px auto;*/
        margin:0px !important;
    }

    table{
       width: 92% !important;

            margin: 0px auto;
            color:#7f7f7f;
              border-radius: 0px 0px 6px 6px;
    -moz-border-radius: 6px 6px 6px 6px;
    -webkit-border-radius: 6px 6px 6px 6px;
  border-width: 0.5px !important;
  border-style: solid !important;
  border-color: #f3f3f3 !important;
    }
    tr{
        border:1px solid #f3f3f3;
    }
    td{
        border:1px solid #f3f3f3;
           padding: 5px 0px 5px 6px;
            font-size:12px;  
    }
</style>
</head>
<body bgcolor="#FFFFFF" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
    <!--<img src="../images/final.jpg" width="595" height="842" alt="">-->  
    <section id="billbook">
        <table style=" margin-top: 175px !important;">
            <tr>
                <td width="59%" style="padding-left:7px;">Name :<span><%= details.fname + " " +details.lname; %></span></td>
                <td class="text-center">INVOICE</td>
            </tr>
            <tr>
                <td>Address :<%= details.address %></td>
                <td>GSTIN   :   <span  style="padding-left:40px;">547etbdjh787jfh</span></td>
            </tr>

            <tr>
                <td></td>
                <td>Invoice No :</td>
            </tr>

             <tr>
                <td>Phone Number :<%= details.phone%></td>
                <td>Invoice Date :</td>
            </tr>

        </table>

        <table style="margin-top:11px;">
            <tr class="text-center">
                <td width="6.5%">SNo</td>
                <td width="39.5%">Description</td>
                <td width="13%">HSN</td>
                <td width="9.5%">Qty</td>
                <td width="15.5%">Rate</td>
                <td width="16%">Amount</td>
            </tr>

            <tr style="height:242px">
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
            </tr>

            <tr>
                <td colspan="3"  rowspan="2">Rupees In Words : yrtyrtyrty ryrty rty rtyrtyrty ryrty</td>
                <td colspan="2" class="text-center">Taxable Value :</td>
                <td>&nbsp;</td>
            </tr>
            <tr>
                <td colspan="2" style="padding-left:30px;">SGST................%</td>
                <!--<td></td>-->
                <td>&nbsp;</td>
            </tr>

            <tr>
                <td colspan="3" rowspan="3">Terms and Conditions:</td>
                <td colspan="2" style="padding-left:30px;">SGST................%</td>
                <!--<td></td>-->
                <td>&nbsp;</td>
            </tr>

            <tr>
                <td colspan="2" style="padding-left:30px;">SGST................%</td>
                <!--<td></td>-->
                <td>&nbsp;</td>
            </tr>

            <tr>
                <td colspan="2" style="padding-left:30px;">Grand Total</td>
                <!--<td></td>-->
                <td>&nbsp;</td>
            </tr>
        </table>
    </section>     
</body>

<script>
     window.onload = function(){
        <%=
             pdf.create(html, options).toFile('public/pdf/businesscard.pdf', function(err, res) {
          if (err) {
               console.log(err);
          }
          else{console.log(res);}

        });         
        %>
    }
</script>
</html>

You need to do the rendering on the server, so remove the window.onload script and add this little piece of magic to your app.js 您需要在服务器上进行渲染,因此请删除window.onload脚本,并将此小技巧添加到您的app.js

app.post("/crm",function(req,res){
  console.log(req.body);
  var details = req.body;

  res.render("crm.ejs", { details: details }, function (err, html) {
    pdf.create(html, options).toFile('./public/pdf/businesscard.pdf', function (err, res) {
      if (err) {
        console.log(err);
      }
      else { console.log(res); }
    });

    res.send(html);
  });
});

To understand the code, you need to think of your server response as the following sequence: 要理解代码,您需要将服务器响应视为以下顺序:

  • render the ejs to a html string ejs渲染为html字符串
  • create a pdf from the html string and save it to the local drive html字符串创建pdf并将其保存到本地驱动器
  • send the html string as a response to the browser 发送html字符串作为对浏览器的响应

Calling res.render with a callback allows your view to be rendered to a string, without getting sent to the browser. 通过回调调用res.render可以将视图呈现为字符串,而无需发送到浏览器。 This allows you to call pdf.create in the callback and then manually send the response with res.send 这使您可以在回调中调用pdf.create ,然后使用res.send手动发送响应

This is a screenshot of the business card I was able to create using your code (which is not bad by the way): 这是我可以使用您的代码创建的名片的屏幕截图(顺便说一句还不错):

卡

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM