pdf文件之itextpdf插入html内容以及中文解决方案
简述
目前网上已经有很多种html文件直接转pdf的技术帖子,但是很少有直接将部分html作为段落插入到pdf中,而且也没有一个可以很好的解决中文显示的问题。
因此今天上午围绕这个问题进行了研究,把解决方案分享给大家。
itextpdf基础操作请访问:http://www.cnblogs.com/mvilplss/p/5640598.html
感谢:http://gridmix.blog.51cto.com/4764051/1229585
实现思路
如果想插入html片段,我们使用一个类的静态方法:
1 String html = "<div style='color:green;font-size:20px;'>你好世界!hello world !</div>"; 2 Paragraph context = new Paragraph(); 3 ElementList elementList =XMLWorkerHelper.parseToElementList(htmlString, null); 4 for (Element element : elementList) { 5 context.add(element); 6 } 7 document.add(context);
不过你会发现不能显示中文,这个问题网上有很多种解决方法,但是都不好使。
查看XMLWorkerHelper.parseToElementList(htmlString, null)这个方法的源码,发现
CssAppliers cssAppliers = new CssAppliersImpl(FontFactory.getFontImp());可以进行字体的更换。
1 public static ElementList parseToElementList(String html, String css) throws IOException { 2 // CSS 3 CSSResolver cssResolver = new StyleAttrCSSResolver(); 4 if (css != null) { 5 CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(css.getBytes())); 6 cssResolver.addCss(cssFile); 7 } 8 9 // HTML 10 CssAppliers cssAppliers = new CssAppliersImpl(FontFactory.getFontImp());//这里可以下手对字体进行操作 11 HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers); 12 htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); 13 htmlContext.autoBookmark(false); 14 15 // Pipelines 16 ElementList elements = new ElementList(); 17 ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null); 18 HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end); 19 CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline); 20 21 // XML Worker 22 XMLWorker worker = new XMLWorker(cssPipeline, true); 23 XMLParser p = new XMLParser(worker); 24 p.parse(new ByteArrayInputStream(html.getBytes())); 25 26 return elements; 27 }
因此我们就想到重写XMLWorkerFontProvider类的getFont(*)方法,对于没有显示声明css样式的字体,默认使用undefine字体样式进行设置默认字体。
1 public class MyXMLWorkerHelper { 2 public static class MyFontsProvider extends XMLWorkerFontProvider { 3 public MyFontsProvider() { 4 super(null, null); 5 } 6 7 @Override 8 public Font getFont(final String fontname, String encoding, float size, final int style) { 9 10 String fntname = fontname; 11 if (fntname == null) { 12 fntname = "宋体"; 13 } 14 return super.getFont(fntname, encoding, size, style); 15 } 16 } 17 18 public static ElementList parseToElementList(String html, String css) throws IOException { 19 // CSS 20 CSSResolver cssResolver = new StyleAttrCSSResolver(); 21 if (css != null) { 22 CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(css.getBytes())); 23 cssResolver.addCss(cssFile); 24 } 25 26 // HTML 27 MyFontsProvider fontProvider = new MyFontsProvider(); 28 CssAppliers cssAppliers = new CssAppliersImpl(fontProvider); 29 HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers); 30 htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); 31 htmlContext.autoBookmark(false); 32 33 // Pipelines 34 ElementList elements = new ElementList(); 35 ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null); 36 HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end); 37 CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline); 38 39 // XML Worker 40 XMLWorker worker = new XMLWorker(cssPipeline, true); 41 XMLParser p = new XMLParser(worker); 42 html = html.replace("<br>", "").replace("<hr>", "").replace("<img>", "").replace("<param>", "") 43 .replace("<link>", ""); 44 p.parse(new ByteArrayInputStream(html.getBytes())); 45 46 return elements; 47 } 48 49 }
因为XMLWork不支持html的单标签,所以要对但标签进行过滤。不然就会报错:Invalid nested tag div found, expected closing tag br