利用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完成
时间: 2024-08-02 06:56:08

利用Java动态生成 PDF 文档的相关文章

自动把动态的jsp页面(或静态html)生成PDF文档,并且上传至服务器

置顶2017年11月06日 14:41:04 阅读数:2311 这几天,任务中有一个难点是把一个打印页面自动给生成PDF文档,并且上传至服务器,然而公司框架只有手动上传文档,打印时可以保存为PDF在本地吧,所以感到很头疼,刚开始没有方向,所以只有surf the Internet了,网上看了很多资料,渐渐的从一点方向也不懂,到慢慢开始了解怎么着手去做,废话就不说了, 我看网上大概介绍了三种方式:Jasper Report . iText . flying sauser jasper report

Java iText使用PDF模板生成PDF文档

我们系统需要生成一个可以打印的PDF文档,老板给了我一个Word文档,按照这个Word文档的格式生成PDF文档. 第一步:下载AdobeAcrobat DC,必须使用这个来制作from域. 第二步:使用AdobeAcrobat DC将Word导成PDF文档. 第三步:由于还要加水印的效果,所以还是使用AdobeAcrobat DC来添加水印,非常方便: 添加水印的方法:使用AdobeAcrobat DC打开PDF文档,"工具"->"编辑PDF"->&qu

利用PDFLib生成PDF文档

本文代码生成的PDF文档效果图 一.PDF介绍 PDF是Portable Document Format的缩写,PDF文件格式是国际通用的电子文档交换事实标准,被许多国家采用作为电子文档交换.PDF文件可以在各种平台下阅读.编辑.发布.该文件格式支持字体.图像.甚至任何附件的嵌入.您可以通过免费的Adobe Acrobat Reader来阅读.编辑PDF文档. 二.PDFLib介绍 PDFLib是用于创建PDF文档的开发库,提供了简单易用的API,隐藏了创建PDF的复杂细节且不需要第3方软件的支

使用PHP生成PDF文档

原文:使用PHP生成PDF文档 实际工作中,我们要使用PHP动态的创建PDF文档,目前有许多开源的PHP创建PDF的类库,今天我给大家来介绍一款优秀的PDF库,它就是TCPDF,TCPDF是一个用于快速生成PDF文件的PHP5函数包.TCPDF基于FPDF进行扩展和改进,增强了实用功能. 使用PHP生成PDF文档 实际工作中,我们要使用PHP动态的创建PDF文档,目前有许多开源的PHP创建PDF的类库,今天我给大家来介绍一款优秀的PDF库,它就是TCPDF,TCPDF是一个用于快速生成PDF文件

C#动态生成Word文档并填充数据

C#也能动态生成Word文档并填充数据 http://www.cnblogs.com/qyfan82/archive/2007/09/14/893293.html 引用http://blog.csdn.net/mengyao/archive/2007/09/13/1784079.aspx using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.

使用PDFLib生成PDF文档教程

一.PDF介绍PDF是Portable Document Format的缩写,PDF文件格式是国际通用的电子文档交换事实标准,被许多国家采用作为电子文档交换.PDF文件可以在各种平台下阅读.编辑.发布.该文件格式支持字体.图像.甚至任何附件的嵌入.您可以通过免费的Adobe Acrobat Reader来阅读.编辑PDF文档. 二.PDFLib介绍PDFLib是用于创建PDF文档的开发库,提供了简单易用的API,隐藏了创建PDF的复杂细节且不需要第3方软件的支持.PDFLib库对于个人是免费的,

C#生成PDF文档,读取TXT文件内容

using System.IO;using iTextSharp.text;using iTextSharp.text.pdf; //需要在项目里引用ICSharpCode.SharpZipLib.dll和itextsharp.dllpublic string TxtFilePath;public string SavePdfPath;//保存PDF的路径 #region 读取TXT内容        private string ReadXieyi(string FilePath)      

Java生成PDF文档(表格、列表、添加图片等)

需要的两个包及下载地址: (1)iText.jar:http://download.csdn.net/source/296416 (2)iTextAsian.jar(用来进行中文的转换):http://download.csdn.net/source/172399 代码如下: 1 import java.awt.Color; 2 import java.io.FileOutputStream; 3 import com.lowagie.text.Cell; 4 import com.lowagi

用Aspose.Words for .NET动态生成word文档中的数据表格

1.概述 最近项目中有一个这样的需求:导出word 文档,要求这个文档的格式不是固定的,用户可以随便的调整,导出内容中的数据表格列是动态的,例如要求导出姓名和性别,你就要导出这两列的数据,而且这个文档不是导出来之后再调整而是导出来后已经是调整过了的.看到这里,您也许马上想到用模板导出!而且.NET中自带有这个组件:Microsoft.Office.Interop.Word,暂且可以满足需求吧.但这个组件也是有局限性的,例如客户端必须装 office组件,而且编码复杂度高.最麻烦的需求是后面那个-