- 浏览: 717152 次
- 性别:
- 来自: 上海
最新评论
-
A741841403:
附件怎么看不到了呢?
介绍一个PDF的生成方案 -
chunguang_yao:
写得非常好
《Struts2技术内幕》 新书部分篇章连载(一)—— 如何学习开源框架 -
su_chunlong:
rrredriver 写道极赞的文章,感谢楼主!有一个问题想请 ...
SpringMVC深度探险(三) —— DispatcherServlet与初始化主线 -
qq_32671287:
...
SpringMVC深度探险(一) —— SpringMVC前传 -
shenghuorulan:
看的好爽,可不可以这么笼统的概括一个框架的学习过程1,框架要解 ...
SpringMVC深度探险(二) —— SpringMVC概览
在Java世界,要想生成PDF,方案不少。最近一直在和这个东西打交道,所以简单做一个小结吧。
在此之前,先来勾画一下我心中比较理想的一个解决方案。在企业应用中,碰到的比较多的PDF的需求,可能是针对某个比较典型的具备文档特性的内容,导出成为PDF进行存档。由于我们现在往往使用一些开源框架,诸如ssh来构建我们的应用,所以我们相对熟悉的方案是针对具体的业务逻辑设计实体,使用开源框架来实现我们的业务逻辑。而PDF的导出,最好不要破坏现有的程序框架,甚至能复用我们业务逻辑层的代码。因为如果把PDF作为一种特殊的表现形式的话,实际上它有点类似模板。最佳的情况,是我们能够通过编写某种模板,把PDF的大概样子确定下来,然后把数据和模板做一次整合,得到最后的结果
带着这个目标,开始在网上搜索解决方案。也找到了一些方案,下面简单小结一下:
Jasper Report
看到的市面上采用的最多的方案,是Jasper Report。相关的文档也很多,不过很杂,需要完全掌握,我认为还是有些坡度和时间的。这个时间和坡度我认为主要来自于对iReport这个IDE的反复尝试,对里面的每个属性的摸索。
Jasper Report的设计思路,本身是不违反我上面所说的初衷的。因为我们的努力方向是先生成模板,然后得到数据,最后将两者整合得到结果。但是Jasper Report的问题在于,其生成模板的方式过于复杂,即使有IDE的帮助,我们还是需要对其中的众多规则有所了解才行,否则就会给调试带来极大的麻烦。
所以,我认为Jasper Report是一个半调子方案,这种强依赖于IDE进行可视化编辑的方式令我很不爽。同时,由此带来的诸多的限制,相信也让很多使用者颇为头疼。在经历了一番痛苦的挣扎后,决定放弃使用这种方案。
iText
其实Jasper Report是基于iText的。于是有的人会说,那么直接使用iText不是一种倒退么?的确,直接使用iText似乎就需要直接使用原生的API进行编程了。不过幸好iText其实提供了一些方便的API,通过使用这些API,我们可以直接将HTML代码转化成iText可识别的Document对象,从而导出PDF文档。
这是从网上找到的一个例子。从代码中,我们可以看到,iText本身提供了一个简单的HTML的解析器,它可以把HTML转化成我们需要的PDF的document。
有了这个东西,基本上我的目标就能达成一大半了。接下来我的任务就是根据实际情况去编写HTML代码,然后扔进这个方法,就OK了。而真正的HTML代码,我们则可以在这里使用真正的模板技术,Freemarker或者Velocity去生成我们所需要的内容。当然,这已经是我们熟门熟路的东西了。
正当我觉得这个方案基本能符合我的要求的时候,我也同样找到了它的很多弱项:
1. 无法识别很多HTML的tag和attribute(应该是iText的HTMLParser不够强大)
2. 无法识别CSS
如果说第一点我还可以勉强接受的话,那么第二点我就完全不能接受了。无法识别简单的CSS,就意味着HTML失去了最基本的活力,也无法根据实际要求调整样式。
所以这种方案也必然无法成为我的方案。
flying sauser
在这种情况下,我几乎已经燃起了自己编写一个支持CSS解析的HTML Parser的想法。幸好,在一个非常偶然的情况下,我在google中搜到了这样一个开源项目,它能够满足我的一切需求。这就是flying sauser,项目主页是:https://xhtmlrenderer.dev.java.net/
项目的首页非常吸引人:An XML/XHTML/CSS 2.1 Renderer。这不正是我要的东西么?
仔细再看里面的文档:
完美了。这东西能解析HTML和CSS,而且能输出成image,PDF等格式。哇!我们来看看sample代码(代码丑陋,不过已经能说明问题了):
运行,成功!实在太简单了!API帮你完成了一切!
有了这个东西,我们就可以将PDF的生成流程变成这样:
1) 编写Freemarker或者Velocity模板,打造HTML,勾画PDF的样式(请任意使用CSS)
2) 在你的业务逻辑层引入Freemarker的引擎或者Velocity的引擎,并将业务逻辑层中可以获取的数据和模板,使用引擎生成最终的内容
3) 将我上面的sample代码做简单封装后,调用,生成PDF
这样,我想作为一个web程序员来说,上面的3点,都不会成为你的绊脚石。你可以轻松驾驭PDF了。
在Flying Saucer的官方文档中,有一些Q&A,可以解决读者们大部分的问题。包括PDF的字体、PDF的格式、Image如何处理等等。大家可以尝试着去阅读。
还有一篇文章,好像是作者写的,非常不错:http://today.java.net/pub/a/today/2007/06/26/generating-pdfs-with-flying-saucer-and-itext.html
帅哥,你不要光给我们一个jar包行吗?告诉我们一下,你改的哪个类,哪个方法,顺便把代码贴一下。谢谢啦。
我用的你的包,可是不管用啊。全是中文,仍然没有换行。。
经过尝试,这个问题的确是存在的,不过至今我还没找到解决方案。哎~~~,中文。。。
那你在浏览器里打开pdf 如何实现打印,直接调用浏览器的功能吗?还是调用pdf自己的打印功能实现在线打印?
我发的struts2配置中,inline改为attachment即可让浏览器保存pdf而不是直接打开,另,我在firefox上测试时,直接打开pdf的情况下是显示pdf的打印按钮的,回头在ie上再试试
那你在浏览器里打开pdf 如何实现打印,直接调用浏览器的功能吗?还是调用pdf自己的打印功能实现在线打印?
可以设置output的格式,是附件还是打开。google一下。
在此之前,先来勾画一下我心中比较理想的一个解决方案。在企业应用中,碰到的比较多的PDF的需求,可能是针对某个比较典型的具备文档特性的内容,导出成为PDF进行存档。由于我们现在往往使用一些开源框架,诸如ssh来构建我们的应用,所以我们相对熟悉的方案是针对具体的业务逻辑设计实体,使用开源框架来实现我们的业务逻辑。而PDF的导出,最好不要破坏现有的程序框架,甚至能复用我们业务逻辑层的代码。因为如果把PDF作为一种特殊的表现形式的话,实际上它有点类似模板。最佳的情况,是我们能够通过编写某种模板,把PDF的大概样子确定下来,然后把数据和模板做一次整合,得到最后的结果
带着这个目标,开始在网上搜索解决方案。也找到了一些方案,下面简单小结一下:
Jasper Report
看到的市面上采用的最多的方案,是Jasper Report。相关的文档也很多,不过很杂,需要完全掌握,我认为还是有些坡度和时间的。这个时间和坡度我认为主要来自于对iReport这个IDE的反复尝试,对里面的每个属性的摸索。
Jasper Report的设计思路,本身是不违反我上面所说的初衷的。因为我们的努力方向是先生成模板,然后得到数据,最后将两者整合得到结果。但是Jasper Report的问题在于,其生成模板的方式过于复杂,即使有IDE的帮助,我们还是需要对其中的众多规则有所了解才行,否则就会给调试带来极大的麻烦。
所以,我认为Jasper Report是一个半调子方案,这种强依赖于IDE进行可视化编辑的方式令我很不爽。同时,由此带来的诸多的限制,相信也让很多使用者颇为头疼。在经历了一番痛苦的挣扎后,决定放弃使用这种方案。
iText
其实Jasper Report是基于iText的。于是有的人会说,那么直接使用iText不是一种倒退么?的确,直接使用iText似乎就需要直接使用原生的API进行编程了。不过幸好iText其实提供了一些方便的API,通过使用这些API,我们可以直接将HTML代码转化成iText可识别的Document对象,从而导出PDF文档。
import java.io.FileOutputStream; import java.io.FileReader; import java.util.ArrayList; import com.lowagie.text.Document; import com.lowagie.text.Element; import com.lowagie.text.html.simpleparser.HTMLWorker; import com.lowagie.text.html.simpleparser.StyleSheet; import com.lowagie.text.pdf.PdfWriter; public class MainClass { public static void main(String[] args) throws Exception { Document document = new Document(); StyleSheet st = new StyleSheet(); st.loadTagStyle("body", "leading", "16,0"); PdfWriter.getInstance(document, new FileOutputStream("html2.pdf")); document.open(); ArrayList p = HTMLWorker.parseToList(new FileReader("example.html"), st); for (int k = 0; k < p.size(); ++k) document.add((Element) p.get(k)); document.close(); } }
这是从网上找到的一个例子。从代码中,我们可以看到,iText本身提供了一个简单的HTML的解析器,它可以把HTML转化成我们需要的PDF的document。
有了这个东西,基本上我的目标就能达成一大半了。接下来我的任务就是根据实际情况去编写HTML代码,然后扔进这个方法,就OK了。而真正的HTML代码,我们则可以在这里使用真正的模板技术,Freemarker或者Velocity去生成我们所需要的内容。当然,这已经是我们熟门熟路的东西了。
正当我觉得这个方案基本能符合我的要求的时候,我也同样找到了它的很多弱项:
1. 无法识别很多HTML的tag和attribute(应该是iText的HTMLParser不够强大)
2. 无法识别CSS
如果说第一点我还可以勉强接受的话,那么第二点我就完全不能接受了。无法识别简单的CSS,就意味着HTML失去了最基本的活力,也无法根据实际要求调整样式。
所以这种方案也必然无法成为我的方案。
flying sauser
在这种情况下,我几乎已经燃起了自己编写一个支持CSS解析的HTML Parser的想法。幸好,在一个非常偶然的情况下,我在google中搜到了这样一个开源项目,它能够满足我的一切需求。这就是flying sauser,项目主页是:https://xhtmlrenderer.dev.java.net/
项目的首页非常吸引人:An XML/XHTML/CSS 2.1 Renderer。这不正是我要的东西么?
仔细再看里面的文档:
引用
Flying Saucer is an XML/CSS renderer, which means it takes XML files as input, applies formatting and styling using CSS, and generates a rendered representation of that XML as output. The output may go to the screen (in a GUI), to an image, or to a PDF file. Because we believe most people will be interested in re-using their knowledge of web layout, our main target for content is XHTML 1.0 (strict), an XML document format that standardizes HTML.
完美了。这东西能解析HTML和CSS,而且能输出成image,PDF等格式。哇!我们来看看sample代码(代码丑陋,不过已经能说明问题了):
/* * ITextRendererTest.java * * Copyright 2009 Shanghai TuDou. * All rights reserved. */ package itext; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import org.xhtmlrenderer.pdf.ITextFontResolver; import org.xhtmlrenderer.pdf.ITextRenderer; import com.lowagie.text.pdf.BaseFont; /** * TODO class description * * * @author pcwang * * @version 1.0, 上午11:03:26 create $Id$ */ public class ITextRendererTest { public static void main(String[] args) throws Exception { String inputFile = "conf/template/test.html"; String url = new File(inputFile).toURI().toURL().toString(); String outputFile = "firstdoc.pdf"; OutputStream os = new FileOutputStream(outputFile); ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(url); // 解决中文支持问题 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont("C:/Windows/Fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 解决图片的相对路径问题 renderer.getSharedContext().setBaseURL("file:/D:/Work/Demo2do/Yoda/branch/Yoda%20-%20All/conf/template/"); renderer.layout(); renderer.createPDF(os); os.close(); } }
运行,成功!实在太简单了!API帮你完成了一切!
有了这个东西,我们就可以将PDF的生成流程变成这样:
1) 编写Freemarker或者Velocity模板,打造HTML,勾画PDF的样式(请任意使用CSS)
2) 在你的业务逻辑层引入Freemarker的引擎或者Velocity的引擎,并将业务逻辑层中可以获取的数据和模板,使用引擎生成最终的内容
3) 将我上面的sample代码做简单封装后,调用,生成PDF
这样,我想作为一个web程序员来说,上面的3点,都不会成为你的绊脚石。你可以轻松驾驭PDF了。
在Flying Saucer的官方文档中,有一些Q&A,可以解决读者们大部分的问题。包括PDF的字体、PDF的格式、Image如何处理等等。大家可以尝试着去阅读。
还有一篇文章,好像是作者写的,非常不错:http://today.java.net/pub/a/today/2007/06/26/generating-pdfs-with-flying-saucer-and-itext.html
评论
62 楼
l116116116
2009-12-13
最近要做一个 html的PDF打印的工作,看到了这篇文章,一直也在试图用flying saucer 的方案来实现。在整个过程中,遇到了很多困难,感觉flying saucer 本身在服务器端的解析能力,与浏览器通过http协议的解析能力还有很多的不足。 例如, 缩印,再例如,显示背景图片,再例如,对<table><tr><td>的支持,再例如对 <jsp:include/>,frame的支持(试过@include 语法,原来以为支持,结果也不支持。 难道只能渲染现有代码? )。 不知道大家在使用时感觉什么样。 之前我们曾使用过 客户端的小开源软件,pdf creator。 这个对客户端html的PDF解析相当有效。 美中不足的就是依赖于客户端的安装。 好好的瘦客户端变成胖客户端也有点不好。。。 唉~~~~~
61 楼
l116116116
2009-12-13
楼上的包我试过,加了一个 isChinese 的方法, 对于符合 xhtml语言的 DIV+CSS 样式的还是挺支持的,但对于不被推荐的<table><tr><td> 中的 中文字符貌似支持不了分行。详情见附件。
60 楼
downpour
2009-12-13
yye_javaeye 写道
?怎么会?我用的是挺好的啊,效果看附件
帅哥,你不要光给我们一个jar包行吗?告诉我们一下,你改的哪个类,哪个方法,顺便把代码贴一下。谢谢啦。
59 楼
yye_javaeye
2009-12-13
?怎么会?我用的是挺好的啊,效果看附件
58 楼
lookdd1
2009-12-12
yye_javaeye 写道
中文换行问题解决了,这东西源码里面是将英文按空格分组,每组判断其位置+长度是否超出边界,超出的话将该组丢到下一行,但是中文里面基本没有空格,所以就无奈了。
将其源码改了改,如果是中文,每字一组,如果是英文,还是按照空格分组,这样大概效率会受一些影响,不过好歹是可以用了,而且一般pdf生成我想应该也不会放在需要大访问量的地方吧。附件是打好包的jar,覆盖就可以了
将其源码改了改,如果是中文,每字一组,如果是英文,还是按照空格分组,这样大概效率会受一些影响,不过好歹是可以用了,而且一般pdf生成我想应该也不会放在需要大访问量的地方吧。附件是打好包的jar,覆盖就可以了
我用的你的包,可是不管用啊。全是中文,仍然没有换行。。
57 楼
yye_javaeye
2009-12-04
中文换行问题解决了,这东西源码里面是将英文按空格分组,每组判断其位置+长度是否超出边界,超出的话将该组丢到下一行,但是中文里面基本没有空格,所以就无奈了。
将其源码改了改,如果是中文,每字一组,如果是英文,还是按照空格分组,这样大概效率会受一些影响,不过好歹是可以用了,而且一般pdf生成我想应该也不会放在需要大访问量的地方吧。附件是打好包的jar,覆盖就可以了
将其源码改了改,如果是中文,每字一组,如果是英文,还是按照空格分组,这样大概效率会受一些影响,不过好歹是可以用了,而且一般pdf生成我想应该也不会放在需要大访问量的地方吧。附件是打好包的jar,覆盖就可以了
56 楼
yye_javaeye
2009-11-27
itext2.1.7的这个方法是public int[] getCharBBox(int c) ;而2.0.8的是public int[] getCharBBox(char c) ,我用2.0.8的是没有问题的
另外,downpour,中文那个问题怎么解决啊?我被它源码里那个递归搞得头晕死掉了,搞不明白了
另外,downpour,中文那个问题怎么解决啊?我被它源码里那个递归搞得头晕死掉了,搞不明白了
55 楼
在雨中
2009-11-26
为什么我在测试的时候始终会报一个找不到匹配的方法的异常
代码如下
在使用Itext.jar时,jar包网上下的,版本应该是2.0.x,报的异常如下
把Itext的jar包换成了2.1.7的之后,异常如下
代码如下
package test; import java.io.FileOutputStream; import java.io.OutputStream; import org.xhtmlrenderer.pdf.ITextRenderer; public class PdfGenerate { public static void main(String[] args) throws Exception { String outputFile = "c:/firstdoc.pdf"; OutputStream os = new FileOutputStream(outputFile); ITextRenderer renderer = new ITextRenderer(); String html = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></head><body><p>你好啊!</p><p>这里加入图片</p><p><img src=\"ww.jpg\" width=\"139\" height=\"102\" /></p><p><img src=\"ww.jpg\" width=\"140\" height=\"95\" /></p><p>测试而已!</p><p>hello the world~</p></body></html>"; renderer.setDocumentFromString(html); // 解决图片的相对路径问题 renderer.getSharedContext().setBaseURL("file:/c:/"); renderer.layout(); renderer.createPDF(os); os.close(); System.out.println("生成成功!"); } }
在使用Itext.jar时,jar包网上下的,版本应该是2.0.x,报的异常如下
Exception in thread "main" java.lang.NoSuchMethodError: com.lowagie.text.pdf.BaseFont.getHeight()F
把Itext的jar包换成了2.1.7的之后,异常如下
Exception in thread "main" java.lang.NoSuchMethodError: com.lowagie.text.pdf.BaseFont.getCharBBox(C)[I at org.xhtmlrenderer.pdf.ITextFontResolver$FontDescription.setMetricDefaults(ITextFontResolver.java:679) at org.xhtmlrenderer.pdf.ITextFontResolver$FontDescription.<init>(ITextFontResolver.java:610) at org.xhtmlrenderer.pdf.ITextFontResolver.addCourier(ITextFontResolver.java:410) at org.xhtmlrenderer.pdf.ITextFontResolver.createInitialFontMap(ITextFontResolver.java:390) at org.xhtmlrenderer.pdf.ITextFontResolver.<init>(ITextFontResolver.java:52) at org.xhtmlrenderer.pdf.ITextRenderer.<init>(ITextRenderer.java:115) at org.xhtmlrenderer.pdf.ITextRenderer.<init>(ITextRenderer.java:102) at test.PdfGenerate.main(PdfGenerate.java:12)
54 楼
yye_javaeye
2009-11-20
我也发现这问题了,正在找解决方法,哪位找着了也请共享下啊,呵呵
53 楼
downpour
2009-11-19
xijieqjx 写道
我在转换时,中文的字段到行末都不自动换行都要延长一段看不见,只有英文到本行末尾自动换行,不知道是css的问题,还是flying Scaucer本身就对中文解析的问题?
经过尝试,这个问题的确是存在的,不过至今我还没找到解决方案。哎~~~,中文。。。
52 楼
xijieqjx
2009-11-18
我在转换时,中文的字段到行末都不自动换行都要延长一段看不见,只有英文到本行末尾自动换行,不知道是css的问题,还是flying Scaucer本身就对中文解析的问题?
51 楼
ycyk_168
2009-11-12
要怎么设置超链接和书签呢?好像直接用HTML的A标签不行啊!
50 楼
yye_javaeye
2009-11-10
blackbat 写道
yye_javaeye 写道
ie是直接打开还是另存为pdf,应该是浏览器端自己设置的吧,我现在的浏览器就是直接打开,我还发愁怎么样让它不打开呢。。
那你在浏览器里打开pdf 如何实现打印,直接调用浏览器的功能吗?还是调用pdf自己的打印功能实现在线打印?
我发的struts2配置中,inline改为attachment即可让浏览器保存pdf而不是直接打开,另,我在firefox上测试时,直接打开pdf的情况下是显示pdf的打印按钮的,回头在ie上再试试
49 楼
blackbat
2009-11-10
yye_javaeye 写道
ie是直接打开还是另存为pdf,应该是浏览器端自己设置的吧,我现在的浏览器就是直接打开,我还发愁怎么样让它不打开呢。。
那你在浏览器里打开pdf 如何实现打印,直接调用浏览器的功能吗?还是调用pdf自己的打印功能实现在线打印?
48 楼
yye_javaeye
2009-11-10
终于弄好了,图片页眉页脚,分页,用了很多css3的东西,idea不支持,写起来真费劲啊,代码不是很好看,总之功能先完成了,回头再改了。
action:
freemarker:
改写的UserAgent:
struts2 配置文件:
action:
import java.util.List; import java.io.*; import org.apache.struts2.ServletActionContext; import org.xhtmlrenderer.pdf.ITextRenderer; import org.xhtmlrenderer.pdf.ITextFontResolver; import org.w3c.dom.Document; import org.w3c.dom.html.HTMLDocument; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; /** * 报告测试 * */ public class ReportSample extends CommonAction { private IRole roleService; private List<Role> roleList; private String ifExp; private InputStream expIs; private String fileName; public String sample1() { roleList = roleService.getTeacherScopeRoleList(); if ("yes".equals(ifExp)) { try { String ftlDir = ServletActionContext.getServletContext().getRealPath("/ftl/report"); Configuration cfg = new Configuration(); cfg.setDefaultEncoding("UTF-8"); cfg.setDirectoryForTemplateLoading(new File(ftlDir)); cfg.setObjectWrapper(new DefaultObjectWrapper()); Template template = cfg.getTemplate("sample1.ftl"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(baos); template.process(this, osw); osw.flush(); osw.close(); ByteArrayOutputStream pdfOut = new ByteArrayOutputStream(); ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(baos.toString()); ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont("c:/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); renderer.getSharedContext().setUserAgentCallback(new HttpURLUserAgent(renderer.getOutputDevice())); renderer.layout(); renderer.createPDF(pdfOut, true); this.expIs = new ByteArrayInputStream(pdfOut.toByteArray()); baos.close(); pdfOut.close(); fileName = "测试中文.pdf"; } catch (Exception e) { logger.error(e); throw new CommException("export error", e); } return "export"; } else { return "sample1"; } } public IRole getRoleService() { return roleService; } public void setRoleService(IRole roleService) { this.roleService = roleService; } public List<Role> getRoleList() { return roleList; } public void setRoleList(List<Role> roleList) { this.roleList = roleList; } public String getIfExp() { return ifExp; } public void setIfExp(String ifExp) { this.ifExp = ifExp; } public InputStream getExpIs() { return expIs; } public void setExpIs(InputStream expIs) { this.expIs = expIs; } public String getFileName() { try { return new String(fileName.getBytes(),"ISO8859-1"); } catch (UnsupportedEncodingException e) { return "test.pdf"; } } public void setFileName(String fileName) { this.fileName = fileName; } }
freemarker:
<html> <head> <title>报告测试1</title> <style type="text/css"> <!-- body { font-family: SimSun; } table { -fs-table-paginate: paginate; } 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; border: thin solid black; 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); } --> </style> </head> <body> <div id="header-left" class="header-left" align="left"><img src="http://localhost:8081/xxx/images/switch_left.gif" width="10" height="10"/>ttt<hr/>打印日期1:</div> <div id="header-right" class="header-right" align="right">报告对象:<hr/>产生日期1:</div> <div id="footer-left" class="footer-left" align="left"><hr/>Copyright 2000</div> <div id="footer-right" class="footer-right" align="right"><hr/>第 <span id="pagenumber"/> 页</div> <table border="0" width="100%" height="100%" cellpadding="0" cellspacing="0"> <tr> <td colspan="10" align="center"><img width="500" height="300" src="http://localhost:8081/xxx/report/barChartSample!sample1.action"/> </td> </tr> <tr> <td>id</td> <td>名称</td> <td>创建时间</td> <td>角色类型</td> <td>适用范围</td> </tr> <#assign i=0> <#list roleList as role> <#assign i = i+1> <tr> <td>${role.roleId}</td> <td>${role.roleName}</td> <td>${role.createTime?datetime}</td> <td>${role.roleTypeId}</td> <td>${role.roleApplyScopeId}</td> </tr> </#list> </table> </body> </html>
改写的UserAgent:
import org.xhtmlrenderer.pdf.ITextUserAgent; import org.xhtmlrenderer.pdf.ITextOutputDevice; import org.xhtmlrenderer.pdf.ITextFSImage; import org.xhtmlrenderer.resource.ImageResource; import org.xhtmlrenderer.resource.CSSResource; import org.xhtmlrenderer.util.XRLog; import java.io.IOException; import java.io.InputStream; import java.io.ByteArrayOutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.LinkedHashMap; import com.lowagie.text.Image; /** * 修改xhtmlrenderer获取css和image资源的方式为网络 * */ @SuppressWarnings("unchecked") public class HttpURLUserAgent extends ITextUserAgent { /** * an LRU cache */ private int imageCacheCapacity = 16; private LinkedHashMap imageCache = new LinkedHashMap(imageCacheCapacity, 0.75f, true) { private static final long serialVersionUID = -2333998499957890105L; protected boolean removeEldestEntry(java.util.Map.Entry eldest) { return size() > imageCacheCapacity; } }; public HttpURLUserAgent(ITextOutputDevice outputDevice) { super(outputDevice); } @Override public CSSResource getCSSResource(String uri) { InputStream is = null; uri = resolveURI(uri); try { URLConnection uc = new URL(uri).openConnection(); uc.connect(); is = uc.getInputStream(); } catch (MalformedURLException e) { XRLog.exception("bad URL given: " + uri, e); } catch (IOException e) { XRLog.exception("IO problem for " + uri, e); } return new CSSResource(is); } @Override public ImageResource getImageResource(String uri) { ImageResource ir; uri = resolveURI(uri); ir = (ImageResource) imageCache.get(uri); if (ir == null) { try { ir = new ImageResource(new ITextFSImage(Image.getInstance(new URL(uri)))); } catch (Exception e) { e.printStackTrace(); } imageCache.put(uri, ir); } if (ir == null) ir = new ImageResource(null); return ir; } }
struts2 配置文件:
<action name="reportSample" class="action.ReportSample"> <result name="sample1" type="freemarker">/ftl/report/sample1.ftl</result> <result name="export" type="stream"> <param name="inputName">expIs</param> <param name="contentType">application/pdf</param> <param name="contentDisposition">inline;filename="${fileName}"</param> </result> </action>
47 楼
downpour
2009-11-10
yye_javaeye 写道
ie是直接打开还是另存为pdf,应该是浏览器端自己设置的吧,我现在的浏览器就是直接打开,我还发愁怎么样让它不打开呢。。
可以设置output的格式,是附件还是打开。google一下。
46 楼
yye_javaeye
2009-11-10
ie是直接打开还是另存为pdf,应该是浏览器端自己设置的吧,我现在的浏览器就是直接打开,我还发愁怎么样让它不打开呢。。
45 楼
JackAndroid
2009-11-10
这下写PDF文件确实方便了很多了,谢谢楼主分享。
44 楼
blackbat
2009-11-10
能不能实现ie打开pdf文件 啊?
或者说直接在线打印pdf文件,而不用下载后再打印,或者通过applet来实现?
或者说直接在线打印pdf文件,而不用下载后再打印,或者通过applet来实现?
43 楼
yye_javaeye
2009-11-09
就现在这样吧,我觉得挺好,呵呵
因为图片是动态画的,每个人访问都会不一样,本地缓存会很多的
因为图片是动态画的,每个人访问都会不一样,本地缓存会很多的
发表评论
-
Struts2的一些不尽人意的地方,兼答hantsy
2012-01-06 10:21 4779hantsy 写道 在 Webwork 合并到Apache S ... -
《Struts2技术内幕》 新书部分篇章连载(七)—— ThreadLocal模式
2012-01-05 14:39 14739第4章 源头活水 —— Str ... -
《Struts2技术内幕》 新书部分篇章连载(六)—— 框架的本质
2012-01-05 14:02 4857第2章 固本清源 —— Web ... -
《Struts2技术内幕》自评 —— 尚未完成的话题
2011-12-30 11:11 4210此文接我另外一篇博客:新书上市:《Struts2技术内幕》 ... -
新书上市:《Struts2技术内幕》
2011-12-26 14:28 10564我的新书《Struts2技术内 ... -
《Struts2技术内幕》 新书部分篇章连载(四)—— 核心分发器
2011-10-27 20:15 75469.2核心分发器 —— Dispa ... -
《Struts2技术内幕》 新书部分篇章连载(五)—— 请求响应哲学
2011-10-27 20:01 14059第7章 别具匠心 —— XWork设计原理 众所周知,现代电 ... -
《Struts2技术内幕》 新书部分篇章连载(三)—— 多视角透析Struts2
2011-10-27 19:09 88403.3 多视角透析Struts2 Str ... -
《Struts2技术内幕》 新书部分篇章连载(一)—— 如何学习开源框架
2011-10-27 18:40 161982.6 如何学习开源框架 ... -
《Struts2技术内幕》 新书部分篇章连载(二)—— 面向对象浅谈
2011-10-26 19:46 9731第2章 固本清源 —— Web ... -
《Struts2技术内幕》 新书样章和导读
2011-10-27 20:40 5071由于本书尚未出版,我 ... -
Spring Security 2 配置精讲
2009-01-22 15:19 29437论坛上看了不少Spring Sec ... -
LightURL——打造零配置的Struts2开发方式
2008-09-16 17:39 10091背景 Struts2已经日益成为Web层比较主流的开发框架,它 ... -
若干条J2EE应用中运用“配置”的最佳实践
2008-04-22 17:07 3719本文所提到的所有内容 ... -
OpenSessionInView详解
2006-11-01 17:13 17319OpenSessionInViewFilter是Sprin ... -
一个简单的ServletContextLoader装载器
2006-09-26 10:49 6990在很多项目中,会碰到一种需求,就是在应用服务器启动的时候,把一 ... -
Struts与Spring整合的几种方法
2006-09-12 15:00 23562论坛中用Struts+Spring的人不少,以前的帖子也有问过 ...
相关推荐
**iText PDF生成方案** iText是一个开源的Java库,专门用于创建和修改PDF文档。在IT领域,尤其是在文档处理和报告生成方面,iText是一个非常实用的工具。本方案将详细探讨如何利用iText来生成PDF文件,以及相关的...
1、 pdfWriter1():使用QpdfWriter和Qpainter进行纯文字版的pdf生成和绘制,并进行了分页显示。 Pdf生成在当前目录下的pdf_test.pdf 2、 pdfWriter2():使用QPdfwriter 和QPainter创建pdf报告,关键是对页面的布局...
首先,我们需要一个PDF库,它能够运行在资源有限的MCU上。虽然PDF格式复杂,但有一些轻量级的开源库如`PDFGen`可以帮助我们实现这一目标。根据提供的压缩包包名`PDFGen-master`,我们可以假设这是我们要用的库,它...
本项目提供了一个纯Java实现的解决方案,它能有效地完成多个PDF文件的合并,并且支持自定义目录的生成以及页码的添加。 首先,`PDFUtil.java`是这个项目的核心类,它包含了处理PDF的关键方法。PDFUtil可能包含了...
PDF生成缩略图是将PDF文档中的页面转换成小尺寸的图像表示,通常用于预览、索引或在文件管理器中快速查看PDF内容。在IT领域,这涉及到PDF处理和图像处理技术。以下是一些关于如何在C#中生成PDF缩略图的关键知识点: ...
标题“自动生成PDF文件,C#源码”表明我们讨论的是一个使用C#编程语言创建PDF文件的解决方案。这通常涉及到第三方库的使用,如iTextSharp,它是一个强大的PDF处理库,能够帮助开发者在C#环境中方便地生成、编辑和...
以下是一些关于“Java将PDF生成图片”的核心知识点: 1. **PDF处理库**:在Java中,我们可以使用第三方库如Apache PDFBox、iText和PDF Clown等来处理PDF文档。这些库提供了丰富的API,用于读取、解析和操作PDF文件...
此外,PDF生成器还可能提供一些高级特性,如合并多个文件为一个PDF、添加水印、密码保护等,以满足不同用户的需求。 总的来说,PDF生成器是Windows 7用户便捷创建PDF文档的重要工具。通过理解其工作原理和使用方法...
总的来说,这款“多图片生成一PDF工具”提供了一个简单易用且高效的解决方案,帮助用户快速将图片集合整理成PDF文档,特别适合处理jpg、png和bmp格式的图片。同时,其批量处理功能极大地提升了处理大量图片的效率。...
虽然.NET Framework本身并不直接支持PDF生成,但有许多开源和商业库可供选择,如iTextSharp、PDFsharp、Syncfusion Essential PDF等。这些库提供了API,允许开发者创建、编辑和操作PDF文档。 以iTextSharp为例,这...
总的来说,这款包含注册码的PDF生成器提供了一个便捷的解决方案,帮助用户轻松创建和管理PDF文档。其小巧的体积、简单的操作以及全面的功能使得它成为处理PDF文件的理想选择。用户在享受这些服务的同时,也无需担心...
本文主要介绍了一种保护数据隐私的深度学习训练数据生成方案,该方案基于条件生成对抗网络(CGAN),能够生成大量与真实数据同分布的对抗样本,满足了生成大量带标签训练数据的需求。同时,该方案还结合数据变形方法...
php生成pdf的完全解决方案,不使用phplib插件,完全脚本化执行,完美解决中文乱码问题,支持以下功能: 1、完美支持中文,php生成的pdf不会出现乱码 2、把SQL查询结构生成为pdf中的表格 3、pdf页眉页脚支持中文及...
首先,我们需要一个库来处理PDF生成。一个常用的开源库是iTextSharp,它是一个功能丰富的PDF处理库,支持多种操作,包括创建、编辑和读取PDF文件。要使用iTextSharp,你需要在项目中添加对它的引用。可以通过NuGet包...
在生成PDF时,我们可以借助Flying Saucer库,这是一个能够将HTML转换为PDF的工具。通过将Freemarker模板与Flying Saucer结合,可以方便地将动态数据转换成结构化的PDF文档。例如,你可以创建一个Freemarker模板,...
JavaPDF文件生成是Java开发中一个重要的领域,主要用于创建、编辑和处理PDF文档。iTextPDF是一个流行的开源库,它提供了丰富的API...通过熟练掌握iTextPDF,开发者可以在Java应用程序中实现专业级的PDF生成和处理功能。
4. **集成到应用**:将条码生成功能集成到你的Java应用程序中,可能需要创建一个服务或工具类,提供生成条码的接口。这可能涉及到处理用户输入、验证数据、选择条码格式,以及将生成的条码图像插入到PDF、报告或网页...
【ASP PDF组件与PDF生成技术】 在Web开发中,生成PDF文档是一项常见的需求,用于提供打印友好版本或者方便用户下载的格式。ASP(Active Server Pages)是微软开发的一种服务器端脚本环境,常用于构建动态网页。而...
在当今的信息技术领域,自动化文档生成是一个非常重要的功能,尤其是在企业和监管单位中,自动化的文档生成可以节省大量的人力和时间资源,提高工作效率。为了实现这一目标,使用Freemarker模板引擎结合Office软件...
总之,"简单易用的pdf生成器"通过DOPDF提供了一个便捷的解决方案,使得用户能够快速且轻松地将Word文档转换为PDF,确保内容的准确性和安全性。通过掌握这种工具的使用,无论是个人还是专业人士,都能在日常工作中...