使用html-pdf包动态生成pdf

时间:2018-11-13 10:37:26

标签: javascript node.js express npm ejs

我正在使用npm软件包html-pdf

我试图动态生成发票。最终,它创建了PDF文件,但没有保存值到PDF,而是保存了ejs代码。有人知道出了什么问题吗?

您可以使用ejs变量查看以下PDF输出的屏幕截图:

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

现在让我解释一下我的节点应用程序:

我正在使用两个ejs页。一种是home.ejs,我们在其中发布需要填写在PDF中的输入值。 第二页是crm.ejs,这是我的发票模板。在crm.ejs中,我使用的是window.onload函数,因此当所有内容都加载到我的crm.ejs模板中时。然后它将生成PDF。但是仍然只保存ejs变量。

现在是代码

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:

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

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

1 个答案:

答案 0 :(得分:0)

您需要在服务器上进行渲染,因此请删除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);
  });
});

要理解代码,您需要将服务器响应视为以下顺序:

  • ejs渲染为html字符串
  • pdf字符串创建一个html,并将其保存到本地驱动器
  • 发送html字符串作为对浏览器的响应

通过回调调用res.render可以将视图呈现为字符串,而无需发送到浏览器。这使您可以在回调中调用pdf.create,然后使用res.send

手动发送响应

这是我可以使用您的代码创建的名片的屏幕截图(顺便说一句还不错):

card