简述
目前网上已经有很多种html文件直接转pdf的技术帖子,但是很少有直接将部分html作为段落插入到pdf中,而且也没有一个可以很好的解决中文显示的问题。
因此今天上午围绕这个问题进行了研究,把解决方案分享给大家。
itextpdf基础操作请访问:http://www.cnblogs.com/mvilplss/p/5640598.html
感谢:
实现思路
如果想插入html片段,我们使用一个类的静态方法:
1 String html = "你好世界!hello world !";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 // HTML10 CssAppliers cssAppliers = new CssAppliersImpl(FontFactory.getFontImp());//这里可以下手对字体进行操作11 HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);12 htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());13 htmlContext.autoBookmark(false);14 15 // Pipelines16 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 Worker22 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 // CSS20 CSSResolver cssResolver = new StyleAttrCSSResolver();21 if (css != null) {22 CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(css.getBytes()));23 cssResolver.addCss(cssFile);24 }25 26 // HTML27 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 // Pipelines34 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 Worker40 XMLWorker worker = new XMLWorker(cssPipeline, true);41 XMLParser p = new XMLParser(worker);42 html = html.replace("", "").replace("
", "").replace("", "").replace("", "")43 .replace(" ", "");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