Java 实现 HTML 页面转 PDF 解决方案
一、添加 maven 依赖
com.itextpdf
itext-asian
5.2.0
org.xhtmlrenderer
core-renderer
R8
二、java代码实现
@ResponseBody
@RequestMapping(value = "/saveNotification.do",method=RequestMethod.POST)
public void saveNotification(HttpServletRequest request, HttpServletResponse response){
JSONObject resultsObj = new JSONObject();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String date = sdf.format(new Date());
String targetPath = request.getServletContext().getRealPath(File.separator); //项目根路径
String htmlFile = targetPath + "/html/custormer_notification.html"; //目标html网页的地址
String pdfPath = targetPath + "/pdf/";//pdf储存位置
String pdfFile = pdfPath + date + ".pdf";//储存的pdf文件路径
File filePath = new File(pdfPath);
//判断此路径文件夹是否存在
if (!filePath.exists()) {
//如果不存在 ,则创建文件夹/目录
filePath.mkdirs();
}
/*创建 内存中的File对象*/
File file = new File(pdfFile);
//如果有重名文件存在则删除文件,对象对应的硬盘必须删不能存在,如果已经存在 则会抛出IOException异常
if (file.exists()) {
file.delete();
}
try {
OutputStream os = null;
ITextRenderer renderer = new ITextRenderer();
/*第一种*/
// renderer.setDocument(new File(htmlFile).toURI().toString());
/*第二种*/
htmlFile = htmlFile.replace("\\", "/");
File html_file = new File(htmlFile);
FileInputStream inputStream = new FileInputStream(html_file);
//流转换成字符串
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = inputStream.read(b)) != -1;) {
out.append(new String(b, 0, n));
}
String html = out.toString();
renderer.setDocumentFromString(html);
//解决中文支持
ITextFontResolver fontResolver = renderer.getFontResolver();
if("linux".equals(getCurrentOperatingSystem())){
fontResolver.addFont("/usr/share/fonts/chiness/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
}else{
fontResolver.addFont("c:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
}
os = new FileOutputStream(pdfFile);
renderer.layout();
renderer.createPDF(os);
renderer.finishPDF();
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public String getCurrentOperatingSystem(){ String os = System.getProperty("os.name").toLowerCase(); System.out.println("---------当前操作系统是-----------" + os); return os; }
三、注意事项:
1、输入的 HTML 页面必须是标准的 XHTML 页面。页面的顶上必须是这样的格式:
2、语法必须是标准的 HTML 语法:所有标签都必须闭合
3、CSS 中必须指定字体,然后在 Java 代码中设置相应的字体
body { font-family: SimSun;}//此字体对应Java代码中的simsun.ttc,如果需要其他字体,则需要查询相关资料去
/*设定纸张大小 A4纸*/
@page{ size: a4; }
table标签添加 style="table-layout:fixed;word-break:break-strict;"
四、本人踩过的坑:
1、建议自己先编写一个简单的标准html网页进行测试,因为复杂的网页中有的css样式不支持此方法
2、在项目实际应用中会遇到pdf文档右边中文显示不全的问题,原因是itext源码问题,老外做的东西,没有考虑到中文问题。默认提供的包里,中文不会换行,有人修改了源代码,解决了这个问题。下载地址: 【https://www.iteye.com/topic/509417?page=6#1279762】 需要注意的是,在官网提供的jar包里,有两个包,一个是core-renderer.jar,另一个是core-renderer-minimal.jar。引用时,只需引用前者就行。
五、解决中文换行问题:
1、在resources目录下新建lib文件夹,将上面下载的jar包放在此文件夹下
2、在pom.xml文件中引入此本地jar包
org.xhtmlrenderer
core-renderer
0.0.1
system
${project.basedir}/src/main/resources/lib/core-renderer.jar
com.lowagie
itext
2.0.8
system
${project.basedir}/src/main/resources/lib/itext-2.0.8.jar
3、添加maven打包资源位置
org.springframework.boot
spring-boot-maven-plugin
maven-compiler-plugin
1.8
UTF-8
${project.basedir}/src/main/resources/lib
五、解决pdf文件在windows系统和Linux系统在文字显示问题:
windows系统下,此处c:/Windows/Fonts/simsun.ttc默认自带字体,但是linux系统下,此处/usr/share/fonts/chiness/simsun.ttc是不存在字体样式的,而我们的项目需要部署在linux服务器上,所有我的解决办法是:
将windows系统中的simsun.ttc文件copy在项目中,如图所示: