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

原文地址:https://www.cnblogs.com/mvilplss/p/5646675.html