你的位置:首页 > Java教程

[Java教程]生成PDF全攻略


     经历过多少踩坑,翻看过多少类似博客,下载过多少版本的Jar,才能摸索出正确的代码书写方式,才能实现项目经理需求分析书中的功能点。

     本文借一次 JavaEE 生成PDF的颠簸的实现过程,描述中小公司程序员的坎坷成长之路。

     俺上面只所以将成熟大公司排除在外的原因是,大公司一般都有成熟的产品线和技术积淀。

     至少会有完善的建构师团队,有像扫地神僧那样的牛人隐士......

     公司中初级程序员遇到问题,能找到以前实现过的类似功能的代码作为参照,也能咨询技术经理。

     小公司是没有这种福分的,就像昨天早晨"生成PDF"需求到,工期一天,明日要给客户看。

     第一反应是找度娘,关键字 "Java生成PDF",博客不是一般的多,下面简述几种实现方式和实现过程中遇到的问题。

     (目录已列在上面,通过搜索引擎进来的小伙伴,看看上面列表中是否有能解决你问题的,有点到相应的小节,没有就关闭看下一条搜索记录吧....)

1.IText 生成复杂PDF

    度娘中占比例最大的Java 生成PDF实现类库,也是许多技术博客中涉及到技术。

    开源中国中的介绍:http://www.oschina.net/p/itext,好嘞,既然都推荐那就采用这类库看看。

    下载 Jar 也是琳琅满目,让你挑花眼,从 2.1--5.5 应有尽有,有些论坛下载东西还需要注册o(︶︿︶)o 唉。

    这里采用的是最新的版本 5.5,仔细阅读下别人的技术博客或者是官方文档,编码起来确实不是很费劲。笔者将业务抽象实现的类如下:

import com.itextpdf.text.Document;import com.itextpdf.text.Element;import com.itextpdf.text.Font;import com.itextpdf.text.Phrase;import com.itextpdf.text.pdf.BaseFont;import com.itextpdf.text.pdf.PdfPCell;import com.itextpdf.text.pdf.PdfPTable;import com.itextpdf.text.pdf.PdfWriter;import java.io.FileOutputStream;public class createSimplePDF {  private static Font FontChinese;  public static void simplePDF() {    try {      BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);      FontChinese = new Font(bfChinese, 12, Font.NORMAL);      Document document = new Document();      PdfWriter.getInstance(document, new FileOutputStream("F:\\Garbage\\Hello simplePDF.pdf"));      document.open();      PdfPTable table = new PdfPTable(4);      table.addCell(getCell("姓名", 1, 1));      table.addCell(getCell("", 1, 1));      table.addCell(getCell("编号", 1, 1));      table.addCell(getCell("", 1, 1));      table.addCell(getCell("部门", 1, 1));      table.addCell(getCell("", 1, 1));      table.addCell(getCell("岗位名称", 1, 1));      table.addCell(getCell("", 1, 1));      table.addCell(getCell("到职日期", 1, 1));      table.addCell(getCell("", 1, 1));      table.addCell(getCell("预定离职日期", 1, 1));      table.addCell(getCell("", 1, 1));      table.addCell(getCell("事由", 1, 3));      table.addCell(getCell("", 3, 3));      table.addCell(getCell("部门意见", 1, 3));      table.addCell(getCell("", 3, 3));      document.add(table);      document.close();    } catch (Exception e) {      e.printStackTrace();    }  }  public static PdfPCell getCell(String cellValue, int colspan, int rowSpan) {    PdfPCell cell = new PdfPCell();    try {      cell = new PdfPCell(new Phrase(cellValue, FontChinese));      cell.setRowspan(rowSpan);      cell.setColspan(colspan);      cell.setHorizontalAlignment(Element.ALIGN_CENTER);    } catch (Exception e) {      e.printStackTrace();    }    return cell;  }}

2.IText添加对中文的支持

   愉快的将代码编写完成,生成后中文不见了,注意是不见了,不是乱码,抛出的错误如下:

   Font 'STSong-Light' with 'UniGB-UCS2-H' is not recognized

   再次询问度娘,发现IText需要添加另外itext-asian.jar去支持中文,那就添加吧。

   因为自己IText使用的是最新的5.5版本,导致其他低版本的 itext-asian.jar 无法支持。

   最终在一篇博客中寻获解决方法,尝试后奏效,就是上述代码中:

 BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); FontChinese = new Font(bfChinese, 12, Font.NORMAL);

  笔者这里将最新的IText.jar 和 配套的中文支持  itext-asian.jar 放入: http://pan.baidu.com/s/1bqs4km  提取密码: 99eg

  为后面同学节省找 jar 的时间。实现的截图如下:

  其实最终要实现的表格的样子比这个要复杂的多,80%花费时间主要是在调整样式,编译输出--->看样式,到这里其实需求已经能够实现了。

  笔者也是用这种方式实现的,毕竟是给客户演示的。

  这里要感谢的是这位博主的博客,里面有详细的IText 设置段落,标题,表格,加密..........只要你能在生成PDF想到的,这里面基本上都有。

  博客地址:http://rensanning.iteye.com/blog/1538689

3.iTextRenderer HTML转PDF

  iTextRenderer是笔者在实现完功能后发现的类库,支持将HTML生成PDF。

  如果采用这种方式,在后台调整样式什么的,就让它见鬼去把。

  具体的流程如下图:

  

     这才是高大上的解决方案有木有,模版引擎现在也是玲琅满目,具体看你们项目实现。

     这样就不用为繁琐的样式发愁了,定义模版前端查看,注入数据,生成PDF。

        ITextRenderer iTextRenderer = new ITextRenderer();        iTextRenderer.getFontResolver().addFont("C:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);        iTextRenderer.setDocument(new File(currWebcontentPath + reviewHtmlPath).toURI().toString());        iTextRenderer.layout();        String pdfName = getPdfName(testVO);        OutputStream fileOutputStream = new FileOutputStream(currWebcontentPath + pdfPath + pdfName);        iTextRenderer.createPDF(fileOutputStream);        iTextRenderer.finishPDF();

    这里面需要解决的问题还有生成的HTML存放的位置,然后就是跳转到下载页面了,如果你是JavaEE后端开发,这些问题应该都难不到你。

    使用的iTextRenderer的jar同样也放到: http://pan.baidu.com/s/1kTOpM0R  提取密码: y9y2

    具体参考的博客有:

    http://www.tuicool.com/articles/qAFNFja

    http://downpour.iteye.com/blog/509417