• 利用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();}
        }
    5、生成PDF完成
  • 相关阅读:
    JS控制台打印星星,总有你要的那一款~
    css居中方法
    line-height
    position定位
    IE盒子模型
    CSS中的盒模型
    CSS中的BEM命名
    循环语句总结(代码以C#为例)
    程序设计中的数学思维函数总结(代码以C#为例)
    转:SpringBoot 自定义异常@ContollerAdvice ExceptionHandler不起作用
  • 原文地址:https://www.cnblogs.com/xionggeclub/p/6128942.html
Copyright © 2020-2023  润新知