利用Java動態生成 PDF 文檔

利用Java動態生成 PDF 文檔,則須要開源的API。首先咱們先想象需求,在企業應用中,客戶會提出一些複雜的需求,好比會針對具體的業務,構建比較典型的具有文檔性質的內容,通常會導出PDF進行存檔。那麼目前最佳的解決方案,你可能會想到 iText ,對沒錯。。。 iText+(Velocity / Freemarker)能夠實現。不過據我熟悉,iText自己提供的HTML解析器仍是不夠強大,許多HTML標籤和屬性沒法識別,更悲催的是簡單的CSS它不認識,排版調整樣式會讓你頭大的。不要失望,接下來我就來介紹一個比較理想的解決方案 flying-saucer + iText + (Velocity / Freemarker)。
          你們都知道 iText 是一個生成PDF文檔的開源Java庫,可以動態的從XML或者數據庫生成PDF,同時還能夠對文檔進行加密,權限控制,甭且還支持Java/C#等。。。
          flying-saucer也是導出PDF的一種解決方案而且是基於iText的開源API,而且實現了CSS解析器,可以很好的支持CSS2.1,以及少許的CSS3
 
          生成PDF解決方案: Flying-Saucer + iText + Velocity
1.  第一步
將jar包放到你的工程裏,須要的jar以下:
 
     bcprov-jdk15-140.jar
     core-renderer.jar
     iText-2.0.8.jar
     iTextAsian.jar
     velocity-1.4.jar
 
Jar包下載地址:http://code.google.com/p/flying-saucer/downloads/list
2.  第二步
設計模版,進行排版調整樣式,css樣式也能夠導入@import 等,經過Velocity模版引擎動態替換 頁面內容,如下是模版內容:
<?xml version="1.0" encoding="UTF-8" ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>PDF模版</title>
<style type="text/css">
<!--
    body {
        font: 100% Verdana, Arial, Helvetica, sans-serif;
        margin: 0;
        padding: 0;
        text-align: center;
        color: #000000;
    }
    .oneColLiqCtrHdr #container {
        width: 100%; 
        margin: 0 auto;
        text-align: left;
    }
    div.header-left {display: none}
    div.header-right {display: none}
    div.footer-left {display: none}
    div.footer-right {display: none}
    @media print {
        div.header-left {
            display: block;
            position: running(header-left);
        }
        div.header-right {
            display: block;
            position: running(header-right);
        }
        div.footer-left {
            display: block;
            position: running(footer-left);
        }
        div.footer-right {
            display: block;
            position: running(footer-right);
        }
    }
    @page {
        margin: 0.65in;
        padding: 1em;
        @top-left{
            content:element(header-left);
        };
        @top-right {
            content: element(header-right)
        };
        @bottom-left {
            content: element(footer-left)
        };
        @bottom-right {
            content: element(footer-right)
        };
    }
    #pagenumber:before {
        content: counter(page);
    }
    #pagecount:before {
        content: counter(pages);
    }
   .tbClass {
        width:100%;height:100%;
        border-left:1px #000000 solid;
        border-bottom:1px #000000 solid
    }
    .tbClass td {
        border-top:1px #000000 solid;
        border-right:1px #000000 solid
    }
    @page landscape{
        size:841.9pt 595.3pt;
        mso-page-orientation:landscape;
        margin:89.85pt 72.0pt 89.85pt 72.0pt;
        mso-header-margin:42.55pt;
        mso-footer-margin:49.6pt;
        mso-paper-source:0;
        layout-grid:15.6pt;
    }
    div.landscape{
        page:landscape;
    }
    @page portrait{
        size:595.3pt 841.9pt;
        margin:36.0pt 36.0pt 36.0pt 36.0pt;
        mso-header-margin:42.55pt;
        mso-footer-margin:49.6pt;
        mso-paper-source:0;
        layout-grid:16.3pt 0pt;
        mso-layout-grid-char-alt:0;
    }
    div.portrait{
        page:portrait;
    }
-->
</style>
</head>
<body class="oneColLiqCtrHdr">
    <div id="container">
        <div id="header">
            <!--***************頁眉_start*****************-->
            <div id="header-left" class="header-left" align="left">
                頁眉左側
            </div>
            <div id="header-right" class="header-right">
                頁眉右側
            </div>
            <!--***************頁眉_end*****************-->
        </div>
        <div id="footer">
            <!--***************頁腳_start*****************-->
            <div id="footer-left" class="footer-left" align="left">
                頁腳左側
            </div> 
            <div id="footer-right" class="footer-right" align="right">
                頁腳右側
            </div>
            <!--***************頁腳_endt*****************-->
        </div>
        <div id="mainContent">
            <!-- start #mainContent -->
            <div>內容1</div>
            <div class="portrait" style="page-break-after:always"><!--分頁-->
            <div>內容2</div>
            <div class="portrait" style="page-break-after:always"><!--分頁-->
            <div class="landscape">內容3 橫向顯示</div>
            <!-- end #mainContent -->
        </div>
    </div>
</body>
</html>
3.  模版與業務數據整合
   @SuppressWarnings("unchecked")
    //打印業務數據對象baseInfo
    public void getPdf(BASEINFO baseInfo) throws Exception{
      
      String sysurl = PdfBO.class.getProtectionDomain().getCodeSource().getLocation().getPath();
       sysurl = sysurl.substring(0,sysurl.indexOf("WEB-INF/",0));
       sysurl = java.net.URLDecoder.decode(sysurl, "UTF-8");
       //首先建立一個模板引擎的實例
       VelocityEngine engine = new VelocityEngine();
       //模版路徑
        String tempath = sysurl+"\\pdf\\template";
        //設置參數
        engine.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, tempath);
        engine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        engine.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        //初始化
        engine.init();
        //得到模板
        Template template = engine.getTemplate("template.html");
        //建立上下文,填充數據
        VelocityContext    context    = new VelocityContext();
        context.put("baseInfo",baseInfo);
        PrintUtils pdfUtil = new PrintUtils();
        context.put("PrintUtils", pdfUtil);
        //如今,把模板和數據合併,輸出到Writer
        String vmpath = sysurl + "\\pdf\\template\\a.html";
        Writer writer = new PrintWriter(new FileOutputStream(new File(vmpath)));
        template.merge(context,writer);
        writer.flush();
        //生成PDF電子文檔
        String sysurl = PdfBO.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        sysurl = sysurl.substring(0,sysurl.indexOf("WEB-INF/",0));
        sysurl = java.net.URLDecoder.decode(sysurl, "UTF-8");
       //轉換的文檔路徑
       String inFileUrl = sysurl + "\\pdf\\template\\a.html";
       String url = new File(inFileUrl).toURI().toURL().toString();
       //轉換後PDF文件的輸出路徑
       String outFile_url_ = sysurl + "\\pdf\\doc\\a.pdf";
       OutputStream output = new FileOutputStream(outFile_url_);
       //實例ITextRenderer,加載html文檔
       ITextRenderer renderer = new ITextRenderer();
       renderer.setDocument(url);
       //支持中文
       ITextFontResolver fontResolver = renderer.getFontResolver();
       fontResolver.addFont("C:/Windows/Fonts/ARIALUNI.TTF",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
       //PDF頁眉圖片路徑
       renderer.getSharedContext().setBaseURL("file:"+sysurl+"\\images\\a.gif");
       renderer.layout();
       renderer.createPDF(output);
       output.close();
       PdfReader reader = new PdfReader(outFile_url_);
       // 加水印後PDF文件輸出路徑
       String filePath_stamper = sysurl + "\\pdf\\doc\\my.pdf";
       PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(filePath_stamper));
       BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-  UCS2-H",BaseFont.NOT_EMBEDDED);
       int total = reader.getNumberOfPages() + 1;
       //水印圖片的路徑
       String imageFilePath = sysurl + "\\images\\b.gif";
       Image image = Image.getInstance(imageFilePath);
       image.setAbsolutePosition(20, 50);
       image.scalePercent(50);
       PdfContentByte under;
       for (int i = 1; i < total; i++) {
           under = stamper.getUnderContent(i);
           under.addImage(image);
           under.beginText();
           under.setColorFill(Color.CYAN);
           under.setFontAndSize(base, 30);
           under.endText();
       }
       stamper.close();}
    }
五、生成PDF完成
相關文章
相關標籤/搜索