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

置顶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(存入)自己的表里面,基本上大概就是这样。

原文地址:https://www.cnblogs.com/yueguanguanyun/p/9267415.html

时间: 2024-10-12 14:33:25

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

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

一. 需求背景 在一些特殊应用场合,客户希望在服务器上生成文档的同时并填充数据,客户端的页面不显示打开文档,但是服务器上生成文档对服务器压力很大,目前服务器上生成文档第一种就是方式是jacob, 但是局限于windows平台,往往许多JAVA程序运行于其他操作系统,在此不讨论该方案.二是POI. 但是它的excel处理还凑合, word模块还局限于读取word的文本内容,写word文件的功能就更弱:还有一个要命的地方,处理doc格式和处理docx格式的类几乎完全不同,要分开针对不同的格式写不同的

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

前两天帮同学实现在线预览word文档中的内容,而且需要提供可以下载的链接!在网上找了好久,都没有什么可行的方法,只得用最笨的方法来实现了.希望得到各位大神的指教.下面我就具体谈谈自己的实现过程,总结一下学习中的收获. 我相信很多程序员都遇到过,有些word文档希望直接在浏览器中打开进行预览,但是浏览器往往不是很配合,直接就提示下载,不像pdf文档,浏览器可以直接进行预览.Word文档甚至始终都会通过本地的Office软件打开.那么,问题来了,如何可以在线浏览word文档呢? 其实,我在最初的时候

利用Java动态生成 PDF 文档

利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那么目前最佳的解决方案,你可能会想到 iText ,对没错... iText+(Velocity / Freemarker)可以实现.不过据我熟悉,iText本身提供的HTML解析器还是不够强大,许多HTML标签和属性无法识别,更悲催的是简单的CSS它不认识,排版调整样式会让你头大的.不要失望,接下来

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

最近在看一些关于CSS3方面的知识,主要是平时看到网页中有很多用CSS3实现的很炫的效果,所以就打算系统的学习一下.在网上找到很多的文章,但都没有一个好的整理性,比较凌乱.昨天看到w3cplus网站中关于CSS3的一些文章,觉得讲解的比较细,所以就决定以此作为学习的模板,一步步开始. 平时上下班在地铁上经常是拿着手机看小说新闻之类的,考虑到在手机端直接访问这些网页肯定会耗费很大的流量,所以最好是将这些文章下载下来放在手机里看,比如保存成图片或pdf当然是最好的选择. 之前曾在园子里看到某前端高手

html内嵌flex同时向flex页面传参实现pdf文档在线阅读

由于项目需求需要实现pdf文档的上传并在线阅读,在网上看了很多关于html在线阅读pdf文档的文章,遇到各种问题,包括不同浏览器之间,同一个浏览器不同版本等问题,最终没有实现.后来就换了一个思路,用flex实现pdf的在线阅读,但是flex不能实现直接阅读pdf(对我而言不行),于是了解到可以通过将pdf转swf之后再实现阅读.下面就来看看实现具体过程: 1,实现pdf转为swf: 2,flex实现swf文件的在线浏览: 3,html内嵌flex实现pdf在线浏览. 1,pdf转swf (1)要

webAPI 自动生成帮助文档

之前在项目中有用到webapi对外提供接口,发现在项目中有根据webapi的方法和注释自动生成帮助文档,还可以测试webapi方法,功能很是强大,现拿出来与大家分享一下. 先看一下生成的webapi文档. 1.下图展示的是生成帮助文档首页面,其中Values是controller,API下面的列表展示出请求的http方法(Get,POST等),请求的action,方法的描述. 2.点击红框内的链接,打开api方法的详情页面,如下图所示, 3.点击Test API打开如下页面 4.输入参数,点击S

Myeclipse中文件已经上传到服务器目录下,文件也没有被占用,但是页面中无法读取和使用问题的解决方法

这个问题是由于Myeclipse中文件不同步引起的.在Myeclipse中,工程文件是由Myeclipse自动扫描添加的,如果在外部修改了工程目录中的文件但又关闭了自动刷新功能,则会引起文件不同步.此外,在外部没有修改Myeclipse工程中的文件也有可能引起该问题. 解决方法: 有两种解决方法: 1)手动刷新.即在Myeclipse的工程目录中,右键refresh(或者按下F5). 2)配置Myeclipse的选项: a)Myeclipse启动时,刷新workspace,即勾选:window-

asp.net webAPI 自动生成帮助文档并测试

之前在项目中有用到webapi对外提供接口,发现在项目中有根据webapi的方法和注释自动生成帮助文档,还可以测试webapi方法,功能很是强大,现拿出来与大家分享一下. 先看一下生成的webapi文档. 1.下图展示的是生成帮助文档首页面,其中Values是controller,API下面的列表展示出请求的http方法(Get,POST等),请求的action,方法的描述. 2.点击红框内的链接,打开api方法的详情页面,如下图所示, 3.点击Test API打开如下页面 4.输入参数,点击S

Web API 自动生成帮助文档并使用Web API Test Client 测试

之前在项目中有用到webapi对外提供接口,发现在项目中有根据webapi的方法和注释自动生成帮助文档,还可以测试webapi方法,功能很是强大,现拿出来与大家分享一下. 先看一下生成的webapi文档. 1.下图展示的是生成帮助文档首页面,其中Values是controller,API下面的列表展示出请求的http方法(Get,POST等),请求的action,方法的描述. 2.点击红框内的链接,打开api方法的详情页面,如下图所示, 3.点击Test API打开如下页面 4.输入参数,点击S