如何使用 grails 渲染将 html 转换为 pdf?
How do I convert html to pdf with grails rendering?
我有以下模板:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>template seldata</title>
<style>
.invoice-box {
max-width: 800px;
margin: auto;
padding: 30px;
border: 1px solid #eee;
box-shadow: 0 0 10px rgba(0, 0, 0, .15);
font-size: 16px;
line-height: 24px;
font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
color: #555;
}
.invoice-box table {
width: 100%;
line-height: inherit;
text-align: left;
}
.invoice-box table td {
vertical-align: top;
}
.invoice-box table tr.top table td {
padding-bottom: 20px;
}
.invoice-box table tr.top table td.title {
font-size: 45px;
line-height: 45px;
color: #333;
}
.invoice-box table tr.information table td {
padding-bottom: 40px;
}
.invoice-box table tr.heading td {
background: #4B626D;
border-bottom: 1px solid #ddd;
text-align: center;
min-width: 100px;
color: white;
}
.invoice-box table tr.details td {
padding-bottom: 20px;
}
.invoice-box table tr.item td{
border-bottom: 1px solid #eee;
text-align: center;
}
.invoice-box table tr.item.last td {
border-bottom: none;
}
.invoice-box table tr.total td:nth-child(2) {
border-top: 2px solid #eee;
font-weight: bold;
}
@media only screen and (max-width: 600px) {
.invoice-box table tr.top table td {
width: 100%;
display: block;
text-align: center;
}
.invoice-box table tr.information table td {
width: 100%;
display: block;
text-align: center;
}
}
.rtl {
direction: rtl;
font-family: Tahoma, 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
}
.rtl table {
text-align: right;
}
.rtl table tr td:nth-child(2) {
text-align: left;
}
</style>
</head>
<body>
<div class="invoice-box">
<table>
<tr class="top">
<td colspan="2">
<table>
<tr>
<td class="title">
</td>
</tr>
</table>
</td>
</tr>
</table>
<table>
<tr class="information">
<td colspan="2">
<table>
<tr>
<td>
<b>Data Encomenda:</b> ${poos.event_date} <br>
<b>Nome:</b>${poos.name}<br>
<b>Morada:</b> Igreja Velha - Santa Comba<br>
<b>Concelho:</b> Ponte de Lima<br>
<b>Codigo Postal:</b> 4990<br>
<b>Codigo da Empresa:</b> 305160<br>
<b>Codigo de Distribuidor:</b>00000<br>
Da visita ao/a V. Cunha - Ponte de Lima - JF no dia 2018-02-27 resulta o seguinte:
</td>
</tr>
</table>
</td>
</tr>
</table>
<p> <b> Encomendas Grosso - Queijo e Manteiga </b> </p>
<table>
<tr class="heading">
<td>
Marca
</td>
<td>
Produto
</td>
<td>
ID GS1
</td>
<td>
Encomenda
</td>
<td>
Data-Entrega
</td>
<td>
Oferta
</td>
<td>
Observações
</td>
</tr>
<tr class="item">
<td>
Limiano
</td>
<td>
Limiano Bola
</td>
<td>
2902310000009
</td>
<td>
40
</td>
<td>
05-03-2018
</td>
<td>
3
</td>
<td>
1 cx em linha a parte
</td>
</tr>
</table>
</div>
</body>
</html>
我正在使用
ByteArrayOutputStream bytes = pdfRenderingService.render(template: "/templates/offers", model: [poos:poos, tasks:tasks, skus:skus])
但它抛出如下错误:
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 3; The markup in the document preceding the root element must be well-formed.
我该怎么做才能完成这项工作?我已经做了一些研究,我发现这是关于 XML 格式的问题,但我不知道哪里出了问题。已经转到 xHTML 验证器...
谁能帮我弄清楚如何让这个渲染工作?我做错了什么?
(如果这是专门用于 Grails 渲染的,是否还有其他 html 我可以使用的 pdf 库?)
提前致谢!
Grails 渲染插件 - Reference Documentation
您必须 declare DOCTYPE 在 GSP 的开头,例如:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
因此您的模板将 _offers.gsp
如下所示:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta charset="utf-8">
<title>template seldata</title>
<style>
.invoice-box {
max-width: 800px;
margin: auto;
padding: 30px;
border: 1px solid #eee;
box-shadow: 0 0 10px rgba(0, 0, 0, .15);
font-size: 16px;
line-height: 24px;
font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
color: #555;
}
.invoice-box table {
width: 100%;
line-height: inherit;
text-align: left;
}
.invoice-box table td {
vertical-align: top;
}
.invoice-box table tr.top table td {
padding-bottom: 20px;
}
.invoice-box table tr.top table td.title {
font-size: 45px;
line-height: 45px;
color: #333;
}
.invoice-box table tr.information table td {
padding-bottom: 40px;
}
.invoice-box table tr.heading td {
background: #4B626D;
border-bottom: 1px solid #ddd;
text-align: center;
min-width: 100px;
color: white;
}
.invoice-box table tr.details td {
padding-bottom: 20px;
}
.invoice-box table tr.item td{
border-bottom: 1px solid #eee;
text-align: center;
}
.invoice-box table tr.item.last td {
border-bottom: none;
}
.invoice-box table tr.total td:nth-child(2) {
border-top: 2px solid #eee;
font-weight: bold;
}
@media only screen and (max-width: 600px) {
.invoice-box table tr.top table td {
width: 100%;
display: block;
text-align: center;
}
.invoice-box table tr.information table td {
width: 100%;
display: block;
text-align: center;
}
}
.rtl {
direction: rtl;
font-family: Tahoma, 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
}
.rtl table {
text-align: right;
}
.rtl table tr td:nth-child(2) {
text-align: left;
}
</style>
</head>
<body>
<div class="invoice-box">
<table>
<tr class="top">
<td colspan="2">
<table>
<tr>
<td class="title">
</td>
</tr>
</table>
</td>
</tr>
</table>
<table>
<tr class="information">
<td colspan="2">
<table>
<tr>
<td>
<b>Data Encomenda:</b> ${poos.event_date} <br>
<b>Nome:</b>${poos.name}<br>
<b>Morada:</b> Igreja Velha - Santa Comba<br>
<b>Concelho:</b> Ponte de Lima<br>
<b>Codigo Postal:</b> 4990<br>
<b>Codigo da Empresa:</b> 305160<br>
<b>Codigo de Distribuidor:</b>00000<br>
Da visita ao/a V. Cunha - Ponte de Lima - JF no dia 2018-02-27 resulta o seguinte:
</td>
</tr>
</table>
</td>
</tr>
</table>
<p> <b> Encomendas Grosso - Queijo e Manteiga </b> </p>
<table>
<tr class="heading">
<td>
Marca
</td>
<td>
Produto
</td>
<td>
ID GS1
</td>
<td>
Encomenda
</td>
<td>
Data-Entrega
</td>
<td>
Oferta
</td>
<td>
Observações
</td>
</tr>
<tr class="item">
<td>
Limiano
</td>
<td>
Limiano Bola
</td>
<td>
2902310000009
</td>
<td>
40
</td>
<td>
05-03-2018
</td>
<td>
3
</td>
<td>
1 cx em linha a parte
</td>
</tr>
</table>
</div>
</body>
</html>
希望对您有所帮助
我有以下模板:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>template seldata</title>
<style>
.invoice-box {
max-width: 800px;
margin: auto;
padding: 30px;
border: 1px solid #eee;
box-shadow: 0 0 10px rgba(0, 0, 0, .15);
font-size: 16px;
line-height: 24px;
font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
color: #555;
}
.invoice-box table {
width: 100%;
line-height: inherit;
text-align: left;
}
.invoice-box table td {
vertical-align: top;
}
.invoice-box table tr.top table td {
padding-bottom: 20px;
}
.invoice-box table tr.top table td.title {
font-size: 45px;
line-height: 45px;
color: #333;
}
.invoice-box table tr.information table td {
padding-bottom: 40px;
}
.invoice-box table tr.heading td {
background: #4B626D;
border-bottom: 1px solid #ddd;
text-align: center;
min-width: 100px;
color: white;
}
.invoice-box table tr.details td {
padding-bottom: 20px;
}
.invoice-box table tr.item td{
border-bottom: 1px solid #eee;
text-align: center;
}
.invoice-box table tr.item.last td {
border-bottom: none;
}
.invoice-box table tr.total td:nth-child(2) {
border-top: 2px solid #eee;
font-weight: bold;
}
@media only screen and (max-width: 600px) {
.invoice-box table tr.top table td {
width: 100%;
display: block;
text-align: center;
}
.invoice-box table tr.information table td {
width: 100%;
display: block;
text-align: center;
}
}
.rtl {
direction: rtl;
font-family: Tahoma, 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
}
.rtl table {
text-align: right;
}
.rtl table tr td:nth-child(2) {
text-align: left;
}
</style>
</head>
<body>
<div class="invoice-box">
<table>
<tr class="top">
<td colspan="2">
<table>
<tr>
<td class="title">
</td>
</tr>
</table>
</td>
</tr>
</table>
<table>
<tr class="information">
<td colspan="2">
<table>
<tr>
<td>
<b>Data Encomenda:</b> ${poos.event_date} <br>
<b>Nome:</b>${poos.name}<br>
<b>Morada:</b> Igreja Velha - Santa Comba<br>
<b>Concelho:</b> Ponte de Lima<br>
<b>Codigo Postal:</b> 4990<br>
<b>Codigo da Empresa:</b> 305160<br>
<b>Codigo de Distribuidor:</b>00000<br>
Da visita ao/a V. Cunha - Ponte de Lima - JF no dia 2018-02-27 resulta o seguinte:
</td>
</tr>
</table>
</td>
</tr>
</table>
<p> <b> Encomendas Grosso - Queijo e Manteiga </b> </p>
<table>
<tr class="heading">
<td>
Marca
</td>
<td>
Produto
</td>
<td>
ID GS1
</td>
<td>
Encomenda
</td>
<td>
Data-Entrega
</td>
<td>
Oferta
</td>
<td>
Observações
</td>
</tr>
<tr class="item">
<td>
Limiano
</td>
<td>
Limiano Bola
</td>
<td>
2902310000009
</td>
<td>
40
</td>
<td>
05-03-2018
</td>
<td>
3
</td>
<td>
1 cx em linha a parte
</td>
</tr>
</table>
</div>
</body>
</html>
我正在使用
ByteArrayOutputStream bytes = pdfRenderingService.render(template: "/templates/offers", model: [poos:poos, tasks:tasks, skus:skus])
但它抛出如下错误:
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 3; The markup in the document preceding the root element must be well-formed.
我该怎么做才能完成这项工作?我已经做了一些研究,我发现这是关于 XML 格式的问题,但我不知道哪里出了问题。已经转到 xHTML 验证器...
谁能帮我弄清楚如何让这个渲染工作?我做错了什么?
(如果这是专门用于 Grails 渲染的,是否还有其他 html 我可以使用的 pdf 库?)
提前致谢!
Grails 渲染插件 - Reference Documentation
您必须 declare DOCTYPE 在 GSP 的开头,例如:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
因此您的模板将 _offers.gsp
如下所示:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta charset="utf-8">
<title>template seldata</title>
<style>
.invoice-box {
max-width: 800px;
margin: auto;
padding: 30px;
border: 1px solid #eee;
box-shadow: 0 0 10px rgba(0, 0, 0, .15);
font-size: 16px;
line-height: 24px;
font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
color: #555;
}
.invoice-box table {
width: 100%;
line-height: inherit;
text-align: left;
}
.invoice-box table td {
vertical-align: top;
}
.invoice-box table tr.top table td {
padding-bottom: 20px;
}
.invoice-box table tr.top table td.title {
font-size: 45px;
line-height: 45px;
color: #333;
}
.invoice-box table tr.information table td {
padding-bottom: 40px;
}
.invoice-box table tr.heading td {
background: #4B626D;
border-bottom: 1px solid #ddd;
text-align: center;
min-width: 100px;
color: white;
}
.invoice-box table tr.details td {
padding-bottom: 20px;
}
.invoice-box table tr.item td{
border-bottom: 1px solid #eee;
text-align: center;
}
.invoice-box table tr.item.last td {
border-bottom: none;
}
.invoice-box table tr.total td:nth-child(2) {
border-top: 2px solid #eee;
font-weight: bold;
}
@media only screen and (max-width: 600px) {
.invoice-box table tr.top table td {
width: 100%;
display: block;
text-align: center;
}
.invoice-box table tr.information table td {
width: 100%;
display: block;
text-align: center;
}
}
.rtl {
direction: rtl;
font-family: Tahoma, 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
}
.rtl table {
text-align: right;
}
.rtl table tr td:nth-child(2) {
text-align: left;
}
</style>
</head>
<body>
<div class="invoice-box">
<table>
<tr class="top">
<td colspan="2">
<table>
<tr>
<td class="title">
</td>
</tr>
</table>
</td>
</tr>
</table>
<table>
<tr class="information">
<td colspan="2">
<table>
<tr>
<td>
<b>Data Encomenda:</b> ${poos.event_date} <br>
<b>Nome:</b>${poos.name}<br>
<b>Morada:</b> Igreja Velha - Santa Comba<br>
<b>Concelho:</b> Ponte de Lima<br>
<b>Codigo Postal:</b> 4990<br>
<b>Codigo da Empresa:</b> 305160<br>
<b>Codigo de Distribuidor:</b>00000<br>
Da visita ao/a V. Cunha - Ponte de Lima - JF no dia 2018-02-27 resulta o seguinte:
</td>
</tr>
</table>
</td>
</tr>
</table>
<p> <b> Encomendas Grosso - Queijo e Manteiga </b> </p>
<table>
<tr class="heading">
<td>
Marca
</td>
<td>
Produto
</td>
<td>
ID GS1
</td>
<td>
Encomenda
</td>
<td>
Data-Entrega
</td>
<td>
Oferta
</td>
<td>
Observações
</td>
</tr>
<tr class="item">
<td>
Limiano
</td>
<td>
Limiano Bola
</td>
<td>
2902310000009
</td>
<td>
40
</td>
<td>
05-03-2018
</td>
<td>
3
</td>
<td>
1 cx em linha a parte
</td>
</tr>
</table>
</div>
</body>
</html>
希望对您有所帮助