【itext学习之路】--6.将html转成pdf(解决中文不显示)

来源:【itext学习之路】-------(第七篇)将html转成pdf(解决中文不显示)_tomatocc的博客-CSDN博客

在上一篇文章中,我们学习了使用对pdf进行盖章/签章/数字签名,到此为止,常用的pdf操作已经全部实现,但是实际开发中很多人比较喜欢将html转成pdf,本文介绍将html转pdf的方法(之前用的都是itext5,这次需要用到itext7中的html2pdf这个强大的组件)

  • 首先,先贴上代码之前一直使用的itext5的方式,将html转pdf(很多标签无法兼容)
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.ElementList;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.css.CssFile;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.ElementHandlerPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.jfinal.log.Log;
import com.jfinal.template.Engine;

/** 
* @author 作者 : tomatocc
* pdf工具类
*/
public class PdfKit {

	private static Log log = Log.getLog(PdfKit.class);
	
	private PdfKit() {
	}

	/**
	 * Creates a PDF with the words
	 * 
	 * @param html
	 * @param file
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static void creatHtmlpdf(String html, String file) throws IOException, DocumentException {
		// step 1 new Document 默认大小A4
		Document document = new Document(PageSize.A4.rotate());
		// step 2
		PdfWriter.getInstance(document, new FileOutputStream(file));
		// step 3
		document.open();
		// step 4
		Paragraph context = new Paragraph();
		ElementList elementList = parseToElementList(html, null);
		for (Element element : elementList) {
			context.add(element);
		}
		document.add(context);
		// step 5
		document.close();
	}

	/**
	 * 设置字体信息
	 * @return
	 */
	private static Font getFontInf() {
		// 字体路径
        String fontPath =  PathKit.getWebRootPath() + "/WEB-INF/vm/font/simhei.ttf";
        BaseFont baseFont = null;
        Font font = null;
		try {
			// 设置字体路径,字体编码,是否将字体嵌入pdf(默认false)
			baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
			// 设置默认字体数据
	        font = new Font(baseFont, 12f,Font.NORMAL,BaseColor.BLACK);
		} catch (DocumentException e) {
			log.error("get pdf font info DocumentException " , e );
		} catch (IOException e) {
			log.error("get pdf font info IOException " , e );
		}
		return font;
	}
	
	/**
	 * html转pdf 写法
	 * @param html
	 * @param css
	 * @return
	 * @throws IOException
	 */
	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;
	}

	static class MyFontsProvider extends XMLWorkerFontProvider {
		public MyFontsProvider() {
			super(null, null);
		}

		@Override
		public Font getFont(final String fontname, String encoding, float size, final int style) {
 			return getFontInf();
		}
	}

	
	public static void main(String[] args) throws IOException, DocumentException {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		// pdf路径
		String file = "d:/test2.pdf";
		// 读取html模板
		String html = Engine.use().setBaseTemplatePath(PathKit.getWebRootPath()).getTemplate("WEB-INF/vm/test.html").renderToString(paramMap);
		PdfKit.creatHtmlpdf(html, file);
	}
}
  • 下面是html
<html>
<head>
<style>
.col {
	padding: 3px 20px 3px 20px
}
</style>
</head>
<body>
	<div style="background:rgb(230,230,230); padding:5px ;border:1px solidblack;">
		<b style="color:rgb(51,153,255)">测试html</b>
	</div>
	<br />
	<table border="0" style='border-collapse: collapse;'>
		<tr>
			<td class="col">姓名:</td>
			<td class="col">tomatocc</td>
		</tr>
		<tr>
			<td class="col">年龄:</td>
			<td class="col">0age</td>
		</tr>
		<tr>
			<td class="col">性别:</td>
			<td class="col">boy</td>
		</tr>
		<tr>
			<td class="col">职业:</td>
			<td class="col">段子手</td>
		</tr>
	</table>
	<br />
	<br />
	<br />
	<hr />
	<br />
</body>
</html>

接下来我们使用itext7中的html2pdf来实现html转pdf

  1. 首先需要下载jar包 点击下载,maven项目用下面坐标即可。
		  <dependency>
		    <groupId>com.itextpdf</groupId>
		    <artifactId>html2pdf</artifactId>
		    <version>2.1.4</version>
		  </dependency>
  1. 下面是代码部分
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.layout.font.FontProvider;
import com.jfinal.log.Log;
import com.jfinal.template.Engine;

/**
 * itext7中将html转pdf
 */
public class Pdf7Kit {
	private static Log log = Log.getLog(Pdf7Kit.class);
	
	/**
	 * 设置BaseFont
	 * @param fontPath  字体路径
	 * @return
	 */
	private static ConverterProperties creatBaseFont(String fontPath) {
		if(StrKit.isBlank(fontPath)) {
			fontPath =  PathKit.getWebRootPath() + "/WEB-INF/vm/font/simhei.ttf";
		}
		
	    ConverterProperties properties = new ConverterProperties();
	    
	    FontProvider fontProvider = new DefaultFontProvider();
	    FontProgram fontProgram;
		try {
			fontProgram = FontProgramFactory.createFont(fontPath);
		    fontProvider.addFont(fontProgram);
		    properties.setFontProvider(fontProvider);
		    
		} catch (IOException e) {
			log.error("creat base font erro" , e );
		}
	    return properties;
	}
	
	/**
	 * 将html文件转换成pdf
	 * @param htmlPath
	 * @param pdfPath
	 * @param fontPath
	 * @throws IOException
	 */
	public static void creatPdf(String htmlPath , String pdfPath,String fontPath) throws IOException {
		if(StrKit.isBlank(htmlPath) || StrKit.isBlank(pdfPath)) {
			log.warn("html2pdf fail. htmlPath or pdfPath is null .");
			return;
		}
		// 拼接html路径
		String src = PathKit.getWebRootPath() + htmlPath;
		
		ConverterProperties properties = creatBaseFont(fontPath);
		HtmlConverter.convertToPdf(new File(src), new File(pdfPath),properties);

	}
	
	/**
	 * 通过模板创建pdf
	 * @param html html路径
	 * @param pdf 生成的pdf路径
	 * @param font  字体文件路径
	 * @param paramMap 参数
	 * @throws IOException
	 */
	public static void creatPdfByTem(String html , String pdf,String font ,Map<String, Object> paramMap) throws IOException {
		if(StrKit.isBlank(html) || StrKit.isBlank(pdf)) {
			log.warn("html2pdf fail. htmlPath or pdfPath is null .");
			return;
		}
		// 拼接临时文件目录
		String srctmp = PathKit.getWebRootPath() + html + StrKit.genUuid(true);
		File file = new File(srctmp);
		// 使用文件模板
		Engine.use().setBaseTemplatePath(PathKit.getWebRootPath()).getTemplate(html).render(paramMap, srctmp);
		ConverterProperties properties = creatBaseFont(font);
		HtmlConverter.convertToPdf(file, new File(pdf),properties);
		
		// 删除临时文件
		if(file.exists()) {
			file.delete();
		}

	}
	
	
	public static void main(String[] args) throws IOException {
		String pdfPath = "d:/test1.pdf";
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("name","tomatocc");
		
		String htmlPath =  "/WEB-INF/vm/test.html";
		// 使用html模板创建pdf
	   // creatPdfByTem(htmlPath, pdfPath, null, paramMap);
	    // 将html转换成pdf
	    creatPdf(htmlPath, pdfPath, null);

	}

}

代码中写了两个方法,第一个是将html转为pdf,是比较简单的,第二种是用html模板,将html转换成pdf,我的模板引擎用的是jfinal模板引擎,其他模板引擎是类似的,需要注意的是HtmlConverter.convertToPdf方法的第一个参数必须是FIle类型,之前模板引擎后的返回值都是String,因此需要做代码改造即可。

这里需要说明一个情况,如果项目中不引入字体文件,那么生成的pdf将不会显示文字(因为生产环境的服务器不会有任何字体文件,而本地运行的话,会自动去电脑中的字体文件库中去寻找字体文件),因此,如果是需要发布的项目,务必将字体文件放到项目中,然后进行使用。

1、解决中文问题 2、附字体 3、动态html拼接转pdf public static void htmlCodeComeString(String linkcss,String htmlCode, String outputFile,String title) throws Exception { OutputStream os = new FileOutputStream(outputFile); ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(getConversionHtmlCode(linkcss,htmlCode,title)); ITextFontResolver fontResolver = renderer.getFontResolver(); URL fontPath = ItextUtil.class.getResource("simsun.ttc"); fontResolver.addFont(fontPath.toString(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 解决图片的相对路径问题 // renderer.getSharedContext().setBaseURL("file:/F:/teste/html/"); renderer.layout(); renderer.createPDF(os); System.out.println("======转换成功!"); os.close(); os.flush(); } public static void main(String[] args) { ItextUtil itextUtil = new ItextUtil(); String html = ""; html += ""; html += "企业信息"; html += " "; html += " "; html += " 登记日期"; html += " 2006-04-28"; html += " "; html += " "; html += " 纳税人编号"; html += " HSJIHKS002"; html += " "; html += " "; html += " 有效标志"; html += " Y"; html += " "; html += " "; html += " 社会信用代码"; html += " 916101317H"; html += " "; html += " "; html += " 评估机关代码"; html += " 盛世"; html += " "; html += " "; html += " 工商注销日期"; html += " 2006-04-28"; html += " "; html += " "; html += ""; String outputFile = "D:\\pdf\\aa.pdf"; try { itextUtil.htmlCodeComeString("",html,outputFile,""); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("生成结束!!!"); }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值