[英]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> </td>
</tr>
<tr>
<td colspan="2" style="padding-left:30px;">SGST................%</td>
<!--<td></td>-->
<td> </td>
</tr>
<tr>
<td colspan="3" rowspan="3">Terms and Conditions:</td>
<td colspan="2" style="padding-left:30px;">SGST................%</td>
<!--<td></td>-->
<td> </td>
</tr>
<tr>
<td colspan="2" style="padding-left:30px;">SGST................%</td>
<!--<td></td>-->
<td> </td>
</tr>
<tr>
<td colspan="2" style="padding-left:30px;">Grand Total</td>
<!--<td></td>-->
<td> </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: 要理解代码,您需要将服务器响应视为以下顺序:
ejs
to a html
string 将ejs
渲染为html
字符串 pdf
from the html
string and save it to the local drive 从html
字符串创建pdf
并将其保存到本地驱动器 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.