置顶2017年11月06日 14:41:04

阅读数:2311

这几天,任务中有一个难点是把一个打印页面自动给生成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(存入)自己的表里面,基本上大概就是这样。

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

  1. [转载]Java动态填充word文档并上传到服务器

    一. 需求背景 在一些特殊应用场合,客户希望在服务器上生成文档的同时并填充数据,客户端的页面不显示打开文档,但是服务器上生成文档对服务器压力很大,目前服务器上生成文档第一种就是方式是jacob, 但是 ...

  2. [原创]Java动态填充word文档并上传到服务器

    一. 需求背景 在一些特殊应用场合,客户希望在服务器上生成文档的同时并填充数据,客户端的页面不显示打开文档,但是服务器上生成文档对服务器压力很大,目前服务器上生成文档第一种就是方式是jacob, 但是 ...

  3. JSP实现word文档的上传,在线预览,下载

    前两天帮同学实现在线预览word文档中的内容,而且需要提供可以下载的链接!在网上找了好久,都没有什么可行的方法,只得用最笨的方法来实现了.希望得到各位大神的指教.下面我就具体谈谈自己的实现过程,总结一 ...

  4. 利用Java动态生成 PDF 文档

    利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...

  5. 将w3cplus网站中的文章页面提取并导出为pdf文档

    最近在看一些关于CSS3方面的知识,主要是平时看到网页中有很多用CSS3实现的很炫的效果,所以就打算系统的学习一下.在网上找到很多的文章,但都没有一个好的整理性,比较凌乱.昨天看到w3cplus网站中 ...

  6. JSP生成WORD文档,EXCEL文档及PDF文档的方法

    转自:https://www.jb51.net/article/73528.htm 本文实例讲述了JSP生成WORD文档,EXCEL文档及PDF文档的方法.分享给大家供大家参考,具体如下: 在web- ...

  7. apiDoc自动生成api文档

    在自定生成api文档方面以前都是使用swagger.json结合swagger工具来生成文档,偶然发现了apidoc这个生成api的工具,发现使用起来比swagger更加简单,下面整理一下使用过程: ...

  8. C# 动态生成word文档 [C#学习笔记3]关于Main(string[ ] args)中args命令行参数 实现DataTables搜索框查询结果高亮显示 二维码神器QRCoder Asp.net MVC 中 CodeFirst 开发模式实例

    C# 动态生成word文档 本文以一个简单的小例子,简述利用C#语言开发word表格相关的知识,仅供学习分享使用,如有不足之处,还请指正. 在工程中引用word的动态库 在项目中,点击项目名称右键-- ...

  9. Django框架深入了解_05 (Django中的缓存、Django解决跨域流程(非简单请求,简单请求)、自动生成接口文档)

    一.Django中的缓存: 前戏: 在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面. 当一个网站的用户访问量很大的时候,每一 ...

随机推荐

  1. Git更新远程仓库代码到本地(转)

    参考链接:https://blog.csdn.net/chailyuan/article/details/53292031 在下载一个较大的github项目以后,当该项目代码更新以后,我们想将更新的内 ...

  2. android屏蔽系统锁屏的办法

    最近在开发一个第三方锁屏,使用中需要屏蔽系统锁屏,故代码如下: 在第三方锁屏的服务中onCreate()方法中(第三方锁屏服务启动时关闭一次系统锁屏服务即可) KeyguardManager mKey ...

  3. 使用@Valid和BindingResult验证请求参数的合法性并处理校验结果

    /** * 添加用户,使用@RequestBody将请求体映射到Action方法参数中 * 使用@Valid注解验证请求参数的合法性 * 使用BindingResult处理校验结果 * @param ...

  4. SpringCloud Feign

    ⒈Feign是什么? Feign是Netflix开发的声明式.模板化的HTTP客户端, Feign可以帮助我们更快捷.优雅地调用HTTP API. SpringCloud微服务项目之间调用是通过Res ...

  5. 【运维】Dell R710如何做Raid0与Raid5

    [写在前面]         这次是在戴尔服务器R710上面尝试的做Raid0和Raid5,亲测成功.         因为创建Raid0与Raid5的方式是一样的,所以就以创建Raid5为例. 1, ...

  6. 题解-bzoj4061 CERC-2012Farm and Factory

    Problem Please contact lydsy2012@163.com! 题意概要:给定\(n\)点\(m\)边无向图,设定两个起点为\(1,2\),现要求在图中增加一个点,并将这个点与其他 ...

  7. css3 弹性效果上下翻转demo

    最近扒了一个有弹性效果上下翻转demo 上图: 上代码: <!DOCTYPE html> <html lang="en"> <head> < ...

  8. vuex之 mapState, mapGetters, mapActions, mapMutations 的使用

    一.介绍 vuex里面的四大金刚:State, Mutations,Actions,Getters (上次记得关于vuex笔记 http://www.cnblogs.com/adouwt/p/8283 ...

  9. java的小数比较反例

    double num = 0.3; System.out.println(num); System.out.println(num - 0.2); System.out.println(num - 0 ...

  10. GO 新开发者要注意的陷阱和常见错误

    转自:http://colobu.com/2015/09/07/gotchas-and-common-mistakes-in-go-golang/ 初级 开大括号不能放在单独的一行 未使用的变量 未使 ...