如何使用grails渲染将html转换为pdf?

时间:2018-03-27 12:06:39

标签: grails groovy xhtml html-to-pdf

我有以下模板:

    <!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 Rendering,我可以使用其他html到pdf库吗?)

提前致谢!

1 个答案:

答案 0 :(得分:0)

Grails渲染插件 - Reference Documentation

您必须在GSP一开始就declare DOCTYPE,如:

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

希望这有助于你