介绍一个PDF的生成方案

baishe62 贡献于2012-10-11

作者 user  创建于2010-09-26 03:57:00   修改者user  修改于2010-09-26 05:42:00字数15161

文档摘要:在Java世界,要想生成PDF,方案不少。最近一直在和这个东西打交道,所以简单做一个小结吧。 在此之前,先来勾画一下我心中比较理想的一个解决方案。在企业应用中,碰到的比较多的PDF的需求,可能是针对某个比较典型的具备文档特性的内 容,导出成为PDF进行存档。由于我们现在往往使用一些开源框架,诸如ssh来构建我们的应用,所以我们相对熟悉的方案是针对具体的业务逻辑设计实体,使 用开源框架来实现我们的业务逻辑。而PDF的导出,最好不要破坏现有的程序框架,甚至能复用我们业务逻辑层的代码。因为如果把PDF作为一种特殊的表现形式的话,实际上它有点类似模板。最佳的情况,是我们能够通过编写某种模板,把PDF的大概样子确定下来,然后把数据和模板做一次整合,得到最后的结果
关键词:

介绍一个PDF的生成方案 http://www.javaeye.com/topic/509417 在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文档。 Java代码 1. import java.io.FileOutputStream;   2. import java.io.FileReader;   3. import java.util.ArrayList;   4.    5. import com.lowagie.text.Document;   6. import com.lowagie.text.Element;   7. import com.lowagie.text.html.simpleparser.HTMLWorker;   8. import com.lowagie.text.html.simpleparser.StyleSheet;   9. import com.lowagie.text.pdf.PdfWriter;   10.    11. public class MainClass {   12.   public static void main(String[] args) throws Exception {   13.     Document document = new Document();   14.     StyleSheet st = new StyleSheet();   15.     st.loadTagStyle("body", "leading", "16,0");   16.     PdfWriter.getInstance(document, new FileOutputStream("html2.pdf"));   17.     document.open();   18.     ArrayList p = HTMLWorker.parseToList(new FileReader("example.html"), st);   19.     for (int k = 0; k < p.size(); ++k)   20.       document.add((Element) p.get(k));   21.     document.close();   22.   }   23. }   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代码(代码丑陋,不过已经能说明问题了): Java代码 1. /*   2. * ITextRendererTest.java *   3. * Copyright 2009 Shanghai TuDou.    4. * All rights reserved.   5. */   6.    7. package itext;   8.    9. import java.io.File;   10. import java.io.FileOutputStream;   11. import java.io.OutputStream;   12.    13. import org.xhtmlrenderer.pdf.ITextFontResolver;   14. import org.xhtmlrenderer.pdf.ITextRenderer;   15.    16. import com.lowagie.text.pdf.BaseFont;   17.    18. /**   19.  * TODO class description *   20.  *  21.  * @author pcwang  22.  *  23.  * @version 1.0, 上午11:03:26  create $Id$  24.  */   25. public class ITextRendererTest {   26.     public static void main(String[] args) throws Exception {   27.         String inputFile = "conf/template/test.html";   28.         String url = new File(inputFile).toURI().toURL().toString();   29.         String outputFile = "firstdoc.pdf";   30.         OutputStream os = new FileOutputStream(outputFile);   31.         ITextRenderer renderer = new ITextRenderer();   32.         renderer.setDocument(url);   33.    34.         // 解决中文支持问题   35.         ITextFontResolver fontResolver = renderer.getFontResolver();   36.         fontResolver.addFont("C:/Windows/Fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);   37.    38.         // 解决图片的相对路径问题   39.         renderer.getSharedContext().setBaseURL("file:/D:/Work/Demo2do/Yoda/branch/Yoda%20-%20All/conf/template/");   40.            41.         renderer.layout();   42.         renderer.createPDF(os);   43.            44.         os.close();   45.     }   46. }   /* * 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 通过实验  中文问题还是解决不了: 楼主提供的解决方法不行,   // 解决中文支持问题           ITextFontResolver fontResolver = renderer.getFontResolver();           fontResolver.addFont("C:\\Windows\\Fonts\\ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);   看了FAQ,提供的方法跟楼主差不多,还是没解决,各位解决了中文的问题没? 楼主,你生成的PDF里有中文字符? 我这里是ok的,请确认你是否在你的CSS种加了对整个body引用你所加入的字体。你光加入,但是不引用是不行滴。 中文可以了。 Java代码 1. ITextFontResolver fontResolver = renderer.getFontResolver();    2. fontResolver.addFont("C:/Windows/fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);   ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont("C:/Windows/fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); Html代码 1.    2.    3.    4.    5. test   6.    7.    16.    17.    18.    19. 显示中文   20.    21.    修改后的xhtmlrenderer核心包已经在 http://yongboy.javaeye.com/blog/510976 上面地址中提供下载,无须显示在CSS中定义字体了,无须如下直接显示定义引入字体: ITextFontResolver fontResolver = renderer.getFontResolver();   fontResolver.addFont("C:/Windows/fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); 估计会方便一些如我之类的新手吧。 JMesa 总结 (2008-08-29 17:33:59) 转载 JMesa 导出pdf中文不能显示问题: JMesa将html通过xhtmlrenderer(core-renderer.jar)解析为pdf文件,xhtmlrenderer集成了itext。 找到xhtmlrenderer包的ITextOutputDevice类,将drawString方法的 cb.setFontAndSize(_font.getFontDescription().getFont(), _font.getSize2D() / _dotsPerPoint); 替换为 try{        cb.setFontAndSize(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), _font.getSize2D() / _dotsPerPoint); }catch(IOException e){        System.out.println("ITextOutputDevice.java drawString方法 字体设置错误!");        e.printStackTrace(); } 关于远程图片,Override了它的ITextUserAgent中的方法,暂时解决了,不过大小无法读取,必须在html中显示指定,代码如下:不知道还有没有更好的解决方法: Java代码 1. import org.xhtmlrenderer.pdf.ITextUserAgent;   2. import org.xhtmlrenderer.pdf.ITextOutputDevice;   3. import org.xhtmlrenderer.pdf.ITextFSImage;   4. import org.xhtmlrenderer.resource.ImageResource;   5. import org.xhtmlrenderer.resource.CSSResource;   6. import org.xhtmlrenderer.util.XRLog;   7.    8. import java.io.IOException;   9. import java.io.InputStream;   10. import java.net.MalformedURLException;   11. import java.net.URL;   12. import java.net.URLConnection;   13. import java.util.LinkedHashMap;   14.    15. import com.lowagie.text.Image;   16.    17. /**  18.  * 修改xhtmlrenderer获取css和image资源的方式为网络  19.  */   20. @SuppressWarnings("unchecked")   21. public class HttpURLUserAgent extends ITextUserAgent {   22.     /**  23.      * an LRU cache  24.      */   25.     private int imageCacheCapacity = 16;   26.     private LinkedHashMap imageCache =   27.             new LinkedHashMap(imageCacheCapacity, 0.75f, true) {   28.                 protected boolean removeEldestEntry(java.util.Map.Entry eldest) {   29.                     return size() > imageCacheCapacity;   30.                 }   31.             };   32.    33.     public HttpURLUserAgent(ITextOutputDevice outputDevice) {   34.         super(outputDevice);   35.     }   36.    37.     @Override   38.     public CSSResource getCSSResource(String uri) {   39.         InputStream is = null;   40.         uri = resolveURI(uri);   41.         try {   42.             URLConnection uc = new URL(uri).openConnection();   43.             uc.connect();   44.             is = uc.getInputStream();   45.         } catch (MalformedURLException e) {   46.             XRLog.exception("bad URL given: " + uri, e);   47.         } catch (IOException e) {   48.             XRLog.exception("IO problem for " + uri, e);   49.         }   50.         return new CSSResource(is);   51.     }   52.    53.     @Override   54.     public ImageResource getImageResource(String uri) {   55.         ImageResource ir;   56.         uri = resolveURI(uri);   57.         ir = (ImageResource) imageCache.get(uri);   58.         if (ir == null) {   59.             try {   60.                 ir = new ImageResource(new ITextFSImage(Image.getInstance(new URL(uri))));   61.             } catch (Exception e) {   62.                 e.printStackTrace();   63.             }   64.             imageCache.put(uri, ir);   65.         }   66.         if (ir == null) ir = new   67.    68.                 ImageResource(null);   69.    70.         return ir;   71.     }   72. }   另,官方主页r8更新说明里面给的分页方法是错误的,官方给的是-fs-table-pagination:paginate,实际应该是-fs-table-paginate:paginate,目前继续钻研页眉页脚 ie是直接打开还是另存为pdf,应该是浏览器端自己设置的吧,我现在的浏览器就是直接打开,我还发愁怎么样让它不打开呢。。 可以设置output的格式,是附件还是打开。google一下。 终于弄好了,图片页眉页脚,分页,用了很多css3的东西,idea不支持,写起来真费劲啊,代码不是很好看,总之功能先完成了,回头再改了。 action: Java代码 1. import java.util.List;   2. import java.io.*;   3.    4. import org.apache.struts2.ServletActionContext;   5. import org.xhtmlrenderer.pdf.ITextRenderer;   6. import org.xhtmlrenderer.pdf.ITextFontResolver;   7. import org.w3c.dom.Document;   8. import org.w3c.dom.html.HTMLDocument;   9. import freemarker.template.Configuration;   10. import freemarker.template.DefaultObjectWrapper;   11. import freemarker.template.Template;   12. import freemarker.template.TemplateException;   13.    14. /**  15.  * 报告测试  16.  *  17.  */   18. public class ReportSample extends CommonAction {   19.     private IRole roleService;   20.     private List roleList;   21.     private String ifExp;   22.     private InputStream expIs;   23.     private String fileName;   24.    25.     public String sample1() {   26.         roleList = roleService.getTeacherScopeRoleList();   27.         if ("yes".equals(ifExp)) {   28.             try {   29.                 String ftlDir = ServletActionContext.getServletContext().getRealPath("/ftl/report");   30.                 Configuration cfg = new Configuration();   31.                 cfg.setDefaultEncoding("UTF-8");   32.                 cfg.setDirectoryForTemplateLoading(new File(ftlDir));   33.                 cfg.setObjectWrapper(new DefaultObjectWrapper());   34.    35.                 Template template = cfg.getTemplate("sample1.ftl");   36.                 ByteArrayOutputStream baos = new ByteArrayOutputStream();   37.                 OutputStreamWriter osw = new OutputStreamWriter(baos);   38.                 template.process(this, osw);   39.                 osw.flush();   40.                 osw.close();   41.    42.                 ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();   43.                 ITextRenderer renderer = new ITextRenderer();   44.                 renderer.setDocumentFromString(baos.toString());   45.    46.                 ITextFontResolver fontResolver = renderer.getFontResolver();   47.                 fontResolver.addFont("c:/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);   48.                 renderer.getSharedContext().setUserAgentCallback(new HttpURLUserAgent(renderer.getOutputDevice()));   49.                 renderer.layout();   50.                 renderer.createPDF(pdfOut, true);   51.                 this.expIs = new ByteArrayInputStream(pdfOut.toByteArray());   52.                 baos.close();   53.                 pdfOut.close();   54.                 fileName = "测试中文.pdf";   55.             } catch (Exception e) {   56.                 logger.error(e);   57.                 throw new CommException("export error", e);   58.             }   59.             return "export";   60.         } else {   61.             return "sample1";   62.         }   63.     }   64.    65.     public IRole getRoleService() {   66.         return roleService;   67.     }   68.    69.     public void setRoleService(IRole roleService) {   70.         this.roleService = roleService;   71.     }   72.    73.     public List getRoleList() {   74.         return roleList;   75.     }   76.    77.     public void setRoleList(List roleList) {   78.         this.roleList = roleList;   79.     }   80.    81.     public String getIfExp() {   82.         return ifExp;   83.     }   84.    85.     public void setIfExp(String ifExp) {   86.         this.ifExp = ifExp;   87.     }   88.    89.     public InputStream getExpIs() {   90.         return expIs;   91.     }   92.    93.     public void setExpIs(InputStream expIs) {   94.         this.expIs = expIs;   95.     }   96.    97.     public String getFileName() {   98.         try {   99.             return new String(fileName.getBytes(),"ISO8859-1");   100.         } catch (UnsupportedEncodingException e) {   101.             return "test.pdf";   102.         }   103.     }   104.    105.     public void setFileName(String fileName) {   106.         this.fileName = fileName;   107.     }   108. }   freemarker: Java代码 1.    2.    3.     报告测试1   4.        5.            71.        72.    73.    74. ttt
打印日期1:
   75. 报告对象:
产生日期1:
   76.    77.
Copyright 2000
   78.
第  页
   79.    80.        81.            83.            84.        85.        86.         id   87.         名称   88.         创建时间   89.         角色类型   90.         适用范围   91.        92.     <#assign i=0>   93.     <#list roleList as role>   94.     <#assign i = i+1>   95.        96.         ${role.roleId}   97.         ${role.roleName}   98.         ${role.createTime?datetime}   99.         ${role.roleTypeId}   100.         ${role.roleApplyScopeId}   101.        102.        103.    104.    105.    报告测试1
ttt
打印日期1:
报告对象:
产生日期1:
<#assign i=0> <#list roleList as role> <#assign i = i+1>
id 名称 创建时间 角色类型 适用范围
${role.roleId} ${role.roleName} ${role.createTime?datetime} ${role.roleTypeId} ${role.roleApplyScopeId}
改写的UserAgent: Java代码 1. import org.xhtmlrenderer.pdf.ITextUserAgent;   2. import org.xhtmlrenderer.pdf.ITextOutputDevice;   3. import org.xhtmlrenderer.pdf.ITextFSImage;   4. import org.xhtmlrenderer.resource.ImageResource;   5. import org.xhtmlrenderer.resource.CSSResource;   6. import org.xhtmlrenderer.util.XRLog;   7.    8. import java.io.IOException;   9. import java.io.InputStream;   10. import java.io.ByteArrayOutputStream;   11. import java.net.MalformedURLException;   12. import java.net.URL;   13. import java.net.URLConnection;   14. import java.util.LinkedHashMap;   15.    16. import com.lowagie.text.Image;   17.    18. /**  19.  * 修改xhtmlrenderer获取css和image资源的方式为网络  20.  *  21.  */   22. @SuppressWarnings("unchecked")   23. public class HttpURLUserAgent extends ITextUserAgent {   24.     /**  25.      * an LRU cache  26.      */   27.     private int imageCacheCapacity = 16;   28.     private LinkedHashMap imageCache =   29.             new LinkedHashMap(imageCacheCapacity, 0.75f, true) {   30.                 private static final long serialVersionUID = -2333998499957890105L;   31.    32.                 protected boolean removeEldestEntry(java.util.Map.Entry eldest) {   33.                     return size() > imageCacheCapacity;   34.                 }   35.             };   36.    37.     public HttpURLUserAgent(ITextOutputDevice outputDevice) {   38.         super(outputDevice);   39.     }   40.    41.     @Override   42.     public CSSResource getCSSResource(String uri) {   43.         InputStream is = null;   44.         uri = resolveURI(uri);   45.         try {   46.             URLConnection uc = new URL(uri).openConnection();   47.             uc.connect();   48.             is = uc.getInputStream();   49.         } catch (MalformedURLException e) {   50.             XRLog.exception("bad URL given: " + uri, e);   51.         } catch (IOException e) {   52.             XRLog.exception("IO problem for " + uri, e);   53.         }   54.         return new CSSResource(is);   55.     }   56.    57.     @Override   58.     public ImageResource getImageResource(String uri) {   59.         ImageResource ir;   60.         uri = resolveURI(uri);   61.         ir = (ImageResource) imageCache.get(uri);   62.         if (ir == null) {   63.             try {   64.                 ir = new ImageResource(new ITextFSImage(Image.getInstance(new URL(uri))));   65.             } catch (Exception e) {   66.                 e.printStackTrace();   67.             }   68.             imageCache.put(uri, ir);   69.         }   70.         if (ir == null) ir = new ImageResource(null);   71.         return ir;   72.     }   73. }   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 配置文件: Java代码 1.    2.     /ftl/report/sample1.ftl   3.        4.         expIs   5.         application/pdf   6.         inline;filename="${fileName}"   7.        8.   
下载需要 6 金币 [金币充值 ]
亲,您也可以通过 分享原创文档 来获得金币奖励!

相关文档

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享文档获得金币 ] 1 人已下载

下载文档