itextpdf 解析带中文的html问题
官网连接 官网上有很多DEMO,下面就说几个我碰到的问题!
Question:
1. 中文不显示 或者是乱码(本打算用Apache pdfbox来实现业务,但是折腾了一个上午也没解决中午乱码问题,就找到itextpdf 替换,如果有人知道怎么解决pdfbox 乱码,请告知,毕竟开源的不要钱!)
2. 页面纸张大小设置
3. 解析带html标签的时候不能解析中文问题
Answer:
1. 对于中文乱码,itextpdf 可以通过读取字体文件解决,STFANGSO.TTF 是我本机上的仿宋的字体文件, 通过如下方式获取字体对象。只能读取.TTF格式文件,其他格式的字体文件会报错,这点要注意。然后再每个new Paragraph(arg1,arg2)的时候,arg1是一个要显示的对象,arg2就是你获得的中文字体。
BaseFont bfChinese =BaseFont.createFont("C:\\Windows\\Fonts\\STFANGSO.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
datatable.addCell(new Paragraph(tableHeader[i], fontChinese));
这样中文问题就解决了。
2. 对于纸张大小设置,参见官方的API
new Document();有三种方式,无参构造,带一个参数的构造和带五个参数的构造。
无参构造自不用解释、
带一个参数的构造,是一个com.itextpdf.text.Rectangle 对象 可以通过com.itextpdf.text.PageSize 点出很多常用的文件大小、
带五个参数的构造,就是可以自定义一张大小的画布了。
3. 由于业务需要将带html标签的文本解析为PDF,但是发现无论解析出来的中文全丢失了,itext自身提供解析html的工具类,但是很多人说需要修改源码,但是我试过也不行。偶然发现一篇使用itext解析html片段,而且解决中文显示问题的博客http://www.cnblogs.com/mvilplss/p/5646675.html,便尝试了一下,居然可以显示中文了(毕竟,完整的html也是多个html片段组成的吗)
自定义一个解析html文本的标签类,可以设定字体大小
public class MyXMLWorkerHelper { public static class MyFontsProvider extends XMLWorkerFontProvider { public MyFontsProvider() { super(null, null); } @Override public Font getFont(final String fontname, String encoding, float size, final int style) { size=9.0f;//可以指定字体大小,不设置默认为12pt String fntname = fontname; if (fntname == null) { fntname = "宋体"; } return super.getFont(fntname, encoding, size, style); } } public static ElementList parseToElementList(String html, String css) throws IOException { // CSS CSSResolver cssResolver = new StyleAttrCSSResolver(); if (css != null) { CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(css.getBytes())); cssResolver.addCss(cssFile); } // HTML MyFontsProvider fontProvider = new MyFontsProvider(); CssAppliers cssAppliers = new CssAppliersImpl(fontProvider); HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers); htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory()); htmlContext.autoBookmark(false); // Pipelines ElementList elements = new ElementList(); ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null); HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end); CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline); // XML Worker XMLWorker worker = new XMLWorker(cssPipeline, true); XMLParser p = new XMLParser(worker); html = html.replace("<br>", "").replace("<hr>", "").replace("<img>", "").replace("<param>", "") .replace("<link>", ""); p.parse(new ByteArrayInputStream(html.getBytes())); return elements; } }
用例Demo 注意字体必须是ttf格式的,我试了用ttc的会报错。
private static void itextPdf() throws Exception { Document document = null; BaseFont bf = null; Font fontChinese = null; bf = BaseFont.createFont("D:\\simsun.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); String dest = "D:\\itextout.pdf"; String inFile = "d:\\in.html"; File file = new File(inFile); StringBuffer sBuffer = new StringBuffer(); BufferedReader reader = null; reader = new BufferedReader(new FileReader(inFile)); String tempString = null; int line = 1; // 一次读入一行,直到读入null为文件结束 while ((tempString = reader.readLine()) != null) { // 显示行号 System.out.println("line " + line + ": " + tempString); line++; sBuffer.append(tempString); } reader.close(); OutputStream outputStream = new FileOutputStream(new File(dest)); try { /** create the right font for chinese **/ bf = BaseFont.createFont("D:\\simsun.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); fontChinese = new Font(bf, 10); document = new Document(PageSize.A4); /** get the html content from javabean and convert to string **/ PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream); document.open(); /** add the head of the pdf **/ Paragraph head = new Paragraph("确认函", new Font(bf, 11)); head.setAlignment(1); // 0 align to the left , 1 align to the center document.add(head); /** add the content of the pdf **/ Paragraph context = new Paragraph(); ElementList elementList =MyXMLWorkerHelper.parseToElementList(sBuffer.toString(), null); for (Element element : elementList) { context.add(element); } document.add(context); document.add(new Paragraph(" ")); document.add(new Paragraph( "亲笔签名/公司公章: _______________________________", fontChinese)); document.add(new Paragraph("日期: ", fontChinese)); document.close(); } catch (Exception e) { e.printStackTrace(); } }