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


     

    这几天,任务中有一个难点是把一个打印页面自动给生成PDF文档,并且上传至服务器,然而公司框架只有手动上传文档,打印时可以保存为PDF在本地吧,所以感到很头疼,刚开始没有方向,所以只有surf the Internet了,网上看了很多资料,渐渐的从一点方向也不懂,到慢慢开始了解怎么着手去做,废话就不说了,

    我看网上大概介绍了三种方式:Jasper Report 、 iText 、 flying sauser  

    jasper report和flying sauser感觉上要比iText的实现要强大一点,但是我实际用的时候对CSS没有太大的需求,因为是一个很简单的表格形式,(如果对pdf的样式有很高的要求,可以去看看flying sauser,这东西能解析HTML和CSS,而且能输出成image,PDF等格式),我用的则是iText,我用的jar是:

    itext-asian-5.2.0、itextpdf-5.5.1、xmlworker-5.5.4、jsoup-1.10.2(此包是java的html解析器)

    1、自动生成PDF,

    下面CreatePdfDocument.java、AsianFontProvider.java是两个工具类,AsianFontProvider 是在CreatePdfDocument里面调用的,而CreatePdfDocument则会在待会儿的实现里面调用。

    1.  
      import com.itextpdf.text.*;
    2.  
      import com.itextpdf.text.pdf.BaseFont;
    3.  
      import com.itextpdf.text.pdf.PdfWriter;
    4.  
      import com.itextpdf.tool.xml.XMLWorkerHelper;
    5.  
      import org.jsoup.Jsoup;
    6.  
       
    7.  
      import java.io.ByteArrayInputStream;
    8.  
      import java.io.FileOutputStream;
    9.  
      import java.io.InputStream;
    10.  
       
    11.  
      /**
    12.  
      * Created by Sinoprof Codeproducer
    13.  
      * User: ck
    14.  
      * Date: 2017-10-31
    15.  
      * Time: 09:25:06
    16.  
      * 实现生成PDF文件
    17.  
      */
    18.  
       
    19.  
      public class CreatePdfDocument {
    20.  
       
    21.  
      /**
    22.  
      * 根据URL提前blog的基本信息,返回结果
    23.  
      * @param URL 例:http://localhost:8080/scm/scm/po/gather/pdftest/pdftesthtml3.html(能直接返回某个html的URL,
    24.  
      * 我开始传url时候被struts1拦截了,应为get不到session的登录人信息,所以得到的是登录页面的html)
    25.  
      * @return
    26.  
      * @throws Exception
    27.  
      */
    28.  
      public static String[] extractHtmlInfo(String URL) throws Exception {
    29.  
      /*这里为什么用数组,是因为返回的时候不仅可以返回选择的html,
    30.  
      还有从document提取其他的信息单独存在数组里返回,然后利用iText在pdf里面组装数据,可以在网上查*/
    31.  
      String[] info = new String[1];
    32.  
      // 直接把URL解析成document,然后调用document.html()解析为html
    33.  
      org.jsoup.nodes.Document doc = Jsoup.connect(URL).get();
    34.  
      // 此doc.select是用来选择完整的html中某一部分这里为第一个div的css为entry的部分,所以你的html上要有div的class为entry哦
    35.  
      org.jsoup.nodes.Element entry = doc.select("div.entry").first();
    36.  
      info[0] = entry.html();
    37.  
      return info;
    38.  
      }
    39.  
       
    40.  
      /**
    41.  
      * 直接通过得到html来取得想要的部分html
    42.  
      * @param html
    43.  
      * @return
    44.  
      * @throws Exception
    45.  
      */
    46.  
      public static String[] extractHtmlInfo2(String html) throws Exception {
    47.  
      String[] info = new String[1];
    48.  
      // 把html转换为document
    49.  
      org.jsoup.nodes.Document doc = Jsoup.parse(html);
    50.  
      // 此doc.select是用来选择完整的html中某一部分这里为第一个div的css为entry的部分,所以你的html上要有div的class为entry哦
    51.  
      org.jsoup.nodes.Element entry = doc.select("div.entry").first();
    52.  
      info[0] = entry.html();
    53.  
      return info;
    54.  
      }
    55.  
       
    56.  
      /**
    57.  
      * 把String 转为 InputStream
    58.  
      * @param content
    59.  
      * @return
    60.  
      */
    61.  
      public static InputStream parse2Stream(String content) {
    62.  
      try {
    63.  
      ByteArrayInputStream stream = new ByteArrayInputStream(
    64.  
      content.getBytes("GBK"));
    65.  
      return stream;
    66.  
      } catch (Exception e) {
    67.  
       
    68.  
      return null;
    69.  
      }
    70.  
      }
    71.  
       
    72.  
       
    73.  
      /**
    74.  
      * 直接把网页内容转为PDF文件
    75.  
      *
    76.  
      * @param
    77.  
      * @throws Exception
    78.  
      */
    79.  
      public static String parseURL2PDFFile(String pdfFile, String html) {
    80.  
      String returnVal = "";
    81.  
      try {
    82.  
      BaseFont bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
    83.  
      false);
    84.  
      // 中文字体定义
    85.  
      Font chFont = new Font(bfCN, 14, Font.NORMAL, BaseColor.BLUE);
    86.  
      Font secFont = new Font(bfCN, 12, Font.NORMAL, new BaseColor(0, 204,
    87.  
      255));
    88.  
      Font textFont = new Font(bfCN, 12, Font.NORMAL, BaseColor.BLACK);
    89.  
       
    90.  
      Document document = new Document(PageSize.A4);
    91.  
      // 设置pdf的背景图片
    92.  
      Image image = Image.getInstance("D:/移动背景图片.jpg");
    93.  
      image.setAlignment(image.UNDERLYING);
    94.  
      image.setAbsolutePosition(0,0);
    95.  
      image.scaleAbsolute(595,842);
    96.  
       
    97.  
      PdfWriter pdfwriter = PdfWriter.getInstance(document,
    98.  
      new FileOutputStream(pdfFile));
    99.  
      pdfwriter.setViewerPreferences(PdfWriter.HideToolbar);
    100.  
      document.open();
    101.  
      document.add(image);
    102.  
      //得到解析的html
    103.  
      String[] blogInfo = extractHtmlInfo2(html);
    104.  
      /*html文件转换为pdf文档
    105.  
      AsianFontProvider()函数是用来解决XMLWorkerHelper.getInstance().parseXHtml()转pdf中文不显示问题*/
    106.  
      XMLWorkerHelper.getInstance().parseXHtml(pdfwriter, document,parse2Stream(blogInfo[0]),null, new AsianFontProvider());
    107.  
       
    108.  
      document.close();
    109.  
      returnVal = "YES";
    110.  
      } catch (Exception e) {
    111.  
      returnVal = "NO";
    112.  
      e.printStackTrace();
    113.  
      } finally {
    114.  
      return returnVal;
    115.  
      }
    116.  
      }
    117.  
      }
     
    1.  
      import com.itextpdf.text.BaseColor;
    2.  
      import com.itextpdf.text.Font;
    3.  
      import com.itextpdf.text.pdf.BaseFont;
    4.  
      import com.itextpdf.tool.xml.XMLWorkerFontProvider;
    5.  
       
    6.  
      /**
    7.  
      * Created by Sinoprof Codeproducer
    8.  
      * User: ck
    9.  
      * Date: 2017-10-31
    10.  
      * Time: 09:25:06
    11.  
      * 用来解决XMLWorkerHelper.getInstance().parseXHtml()转pdf中文不显示问题
    12.  
      */
    13.  
      public class AsianFontProvider extends XMLWorkerFontProvider{
    14.  
       
    15.  
      public Font getFont(final String fontname, final String encoding,
    16.  
      final boolean embedded, final float size, final int style,
    17.  
      final BaseColor color) {
    18.  
      BaseFont bf = null;
    19.  
      try {
    20.  
      bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
    21.  
      } catch (Exception e) {
    22.  
      e.printStackTrace();
    23.  
      }
    24.  
      Font font = new Font(bf, size, style, color);
    25.  
      font.setColor(color);
    26.  
      return font;
    27.  
      }
    28.  
      }



     
     下面时调用生成PDF,我就随便写了个main方法,注意不要直接引用下面这段代码哦,这是两种情况,选一种来试试
    
    
    /**
     * @param args
    */
    public static void main(String[] args) throws Exception {
        // 网页必须是可以直接访问的URL,
    String blogURL = "http://localhost:8080/scm/scm/po/gather/pdftest/pdftesthtml3.html";
        // 传入自己的html,注意html要符合w3c的标准html,因为itexthtml格式有点严格,
    String html = "";
        // PDF最后的输出文档,注意d:/test/itext这些folder要先建好
    String pdfFile = "d:/test/itext/demo-URL.pdf";
        // 直接把网页内容转为PDF文件 但是这个网页必须是可以直接访问的URL,注意在CreatePdfDocument.javaparseURL2PDFFile方法中要调用extractHtmlInfo方法
    Demo4URL2PDF.parseURL2PDFFile(pdfFile, blogURL);
        // 直接传入html的,注意在CreatePdfDocument.javaparseURL2PDFFile方法中要调用extractHtmlInfo2方法
    Demo4URL2PDF.parseURL2PDFFile(pdfFile, html);
    }

    这样子基本就能在你指定的位置生成PDF文档了,但注意前面说过iText对html的样式支持的很少,所以生成的pdf文档比较简单,jtext-asian-5.2.0、itextpdf-5.5.1、xmlworker-5.5.4,这三个jar是我在网上找的支持table标签的,(刚开始找的低版本的jar不支持table,所以我的表格出不来),还有就是AsianFontProvider.java这个类对中文的支持,因为iText的XMLWorkerHelper.getInstance().parseXHtml转PDF的时候,中文不显示,

    (网上说是什么没有默认的中文字体,我看网上有人修改xmlworker源码的,使其默认一个字体),

    但是我没有成功,机缘巧合之下我找到了这种不用修改源码的就像这样

    XMLWorkerHelper.getInstance().parseXHtml(pdfwriter,document,parse2Stream(blogInfo[0]),null,newAsianFontProvider());

    刚好能帮我解决我的需求,结果图片如下:


    下面说说任务中的遇到的困难,上面说自动生成PDF时可以直接传入string类型的html或者URL,但这个URL要是课可以直接访问的,比如说网页的网址,但是我们的项目中有struts1会拦截没有登陆的,没有登陆就会跳转到登录页面,所以每次我用URL的去测试的时候,返回的始终是一个登录页面的html,其实我需要的就是一个动态的jsp生成PDF。

    刚好,又让我找到了现成的方法,其实原理是:得到数据后,让jsp页面不输在浏览器上显示,而是输出到字节流最后以字符的形式返回,这样我就可以得到动态的jsp组装好后输出的静态的html,这样就得到了我想要的html。

    具体的我直接po博主的博客吧http://www.cnblogs.com/Iran1112/p/6013474.html,这里面我学习了怎么让动态的jsp以流的方式输出html。

    至于上传至服务器,要看看自己服务器要怎么存储了,一般的思路:先读写文件比如这样:

    // 输入流
    FileInputStream fi = new FileInputStream(fPath);
    BufferedInputStream bi = new BufferedInputStream(fi);
    // 输出流
    FileOutputStream fo = new FileOutputStream(newFile);
    BufferedOutputStream bo = new BufferedOutputStream(fo);
    // 先定义一个字节缓冲区,减少I/O次数,提高读写效率
    byte[] buf = new byte[1024];
    int len = 0;
    while ((len=bi.read(buf))!=-1){
        bo.write(buf,0,len);
        // 使缓冲的输出字节 被写到底层输出流中 避免电脑断电等特殊情况导致缓冲区中的数据被清空
    bo.flush();
    }
    fi.close();
    fo.close();
    然后拿到文件的信息,比如说:文件名称、存储路径、大小...,再insert(存入)自己的表里面,基本上大概就是这样。
  • 相关阅读:
    爬虫(一)—— 爬取一个简单的网站
    Neutron的安全组原理
    Neutron的防火墙原理
    Openstack Mitaka 负载均衡 LoadBalancerv2
    iptables(四)iptables匹配条件总结之一
    iptables(三)iptables规则管理(增、删、改)
    iptables(二)iptables实际操作之规则查询
    iptables(一)iptables概念
    opensack-mitaka网络性能测试shaker
    neutron二层网络实现
  • 原文地址:https://www.cnblogs.com/yueguanguanyun/p/9267415.html
Copyright © 2020-2023  润新知