首页 > 代码库 > 利用Java动态生成 PDF 文档

利用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 + Velocity1.  第一步将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/list2.  第二步设计模版,进行排版调整样式,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();}    }5、生成PDF完成

 

利用Java动态生成 PDF 文档