java项目中用到了html转pdf的需求,现在写一个自己认为最优方案的总结,虽然还是有一些小的bug

为了保证中文的支持需要在被转换的html添加body的添加中文字体样式,保持这个字体和后边转换pdf的字体一致就可以了,不需要必须是SimSun字体

body{

font-family:SimSun;

}

下面放上jar包的引用pom

注意:org.xhtmlrenderer.core-renderer.R8的jar包,其实需要做一些修改,直接用的话不支持中文换行,可以点击下载支持中文换行的jar包,修改jar包名字替掉R8的jar包

org.xhtmlrenderer

core-renderer

R8

org.apache.commons

commons-lang3

3.0

com.itextpdf

itextpdf

5.5.10

com.itextpdf

html2pdf

2.0.0

这种方式对html里的代码样式要求比较严格,类似xhtml的标准,要求html中的标签都是闭合的,像meta和link这样的标签以及空格 这类的转义符都会导致转换pdf报错,因此最好在之前将html代码进行处理,以下是处理代码:

import java.io.File;

import java.io.FileInputStream;

import com.itextpdf.html2pdf.jsoup.Jsoup;

import com.itextpdf.html2pdf.jsoup.nodes.Document;

import com.itextpdf.html2pdf.jsoup.nodes.Entities;

public class HtmlToXHtmlJsoup {

public static String html2xhtml(String html) {

Document doc = Jsoup.parse(html);

doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml).escapeMode(Entities.EscapeMode.xhtml);

return doc.html();

}

public static void main(String[] args) throws Exception {

// File file = new File("E:\\html2xhtml.html");

File file = new File("report01.html");

FileInputStream input = new FileInputStream(file);

int size = input.available();

byte[] buff = new byte[size];

input.read(buff);

input.close();

String html = new String(buff, "utf-8");

System.out.println("============html===================");

System.out.println(html);

String xhtml = HtmlToXHtmlJsoup.html2xhtml(html);

System.out.println("============xhtml===================");

System.out.println(xhtml);

}

}

图片Base64支持类,没有用到可以不需要此类

import java.io.IOException;

import org.w3c.dom.Element;

import org.xhtmlrenderer.extend.FSImage;

import org.xhtmlrenderer.extend.ReplacedElement;

import org.xhtmlrenderer.extend.ReplacedElementFactory;

import org.xhtmlrenderer.extend.UserAgentCallback;

import org.xhtmlrenderer.layout.LayoutContext;

import org.xhtmlrenderer.pdf.ITextFSImage;

import org.xhtmlrenderer.pdf.ITextImageElement;

import org.xhtmlrenderer.render.BlockBox;

import org.xhtmlrenderer.simple.extend.FormSubmissionListener;

import com.lowagie.text.BadElementException;

import com.lowagie.text.Image;

import com.lowagie.text.pdf.codec.Base64;

/**

* * 图片base64支持,把图片转换为itext自己的图片对象 * @author Administrator *

*/

public class Base64ImgReplacedElementFactory implements ReplacedElementFactory {

/**

* 实现createReplacedElement 替换html中的Img标签

*

* @param c 上下文

* @param box 盒子

* @param uac 回调

* @param cssWidth css宽

* @param cssHeight css高

* @return ReplacedElement

*/

public ReplacedElement createReplacedElement(LayoutContext c, BlockBox box, UserAgentCallback uac, int cssWidth,int cssHeight) {

Element e = box.getElement();

if (e == null) {

return null;

}

String nodeName = e.getNodeName();

// 找到img标签

if (nodeName.equals("img")) {

String attribute = e.getAttribute("src");

FSImage fsImage;

try {

// 生成itext图像

fsImage = buildImage(attribute, uac);

} catch (BadElementException e1) {

fsImage = null;

} catch (IOException e2) {

fsImage = null;

}

if (fsImage != null) {

// 对图像进行缩放

if (cssWidth != -1 || cssHeight != -1) {

fsImage.scale(cssWidth, cssHeight);

}

//if(fsImage.getHeight()>5000) {

//fsImage.scale(cssWidth, 5000);

//}

return new ITextImageElement(fsImage);

}

}

return null;

}

/**

* 编解码base64并生成itext图像

* @param srcAttr

* @param uac

* @return

* @throws IOException

* @throws BadElementException

*/

protected FSImage buildImage(String srcAttr, UserAgentCallback uac) throws IOException,BadElementException {

FSImage fiImg=null;

if (srcAttr.toLowerCase().startsWith("data:image/")) {

String base64Code= srcAttr.substring(srcAttr.indexOf("base64,") + "base64,".length(),srcAttr.length());

byte[] decodedBytes = Base64.decode(base64Code);

fiImg= new ITextFSImage(Image.getInstance(decodedBytes));

}else {

fiImg= uac.getImageResource(srcAttr).getImage();

}

return fiImg;

}

@Override

public void reset() {

}

@Override

public void remove(Element e) {

}

@Override

public void setFormSubmissionListener(FormSubmissionListener listener) {

}

}

具体的java中html转pdf的实现,不需要图片base64支持的可以注释掉if(true)代码块,中文字体支持的Fonts/SimSun.ttc是我自己的字体存放位置,具体的路径需要改为自己的

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.net.MalformedURLException;

import org.xhtmlrenderer.pdf.ITextFontResolver;

import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.DocumentException;

import com.lowagie.text.pdf.BaseFont;

public class HtmltoPDF {

public static void main(String[] ages) throws Exception {

html2pdf("‪C:/Users/I/Desktop/新建文本文档.html", "C:/Users/I/Desktop/新建文本文档.pdf");

}

public static void html2pdf(String inputFile, String outFile) throws Exception {

String url;

OutputStream os = null;

try {

url = new File(inputFile).toURI().toURL().toString();

os = new FileOutputStream(outFile);

ITextRenderer renderer = new ITextRenderer();

renderer.setDocument(url);

// 解决中文不显示问题

ITextFontResolver fontResolver = renderer.getFontResolver();

// 图片base64支持,把图片转换为itext自己的图片对象,如果不需要可以去掉if代码块

if(true) {// 如果携带图片则加上以下代码,将图片标签转换为Itext自己的图片对象

renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());

renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);

}

// 解决图片的相对路径问题

//renderer.getSharedContext().setBaseURL("file:D:/");

/* 字体具体路径:Fonts/SimSun.ttc,所选的字体需要与转换的html中的字体一致,可添加多种字体 */

fontResolver.addFont("Fonts/SimSun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);// 宋体字

renderer.layout();

renderer.createPDF(os);

renderer.finishPDF();

} catch (MalformedURLException e) {

e.printStackTrace();

throw new Exception("生成pdf失败");

} catch (FileNotFoundException e) {

e.printStackTrace();

throw new Exception("生成pdf失败");

} catch (com.lowagie.text.DocumentException e) {

e.printStackTrace();

throw new Exception("生成pdf失败");

} catch (IOException e) {

e.printStackTrace();

throw new Exception("生成pdf失败");

} finally {

if (os != null) {

try {

os.close();

} catch (IOException e) {

e.printStackTrace();

throw new Exception("生成pdf失败");

}

}

}

}

public static void html2pdf2(String html,String outputFile) {

OutputStream os = null;

try {

ITextRenderer renderer = new ITextRenderer();

ITextFontResolver fontResolver = renderer.getFontResolver();

os = new FileOutputStream(outputFile);

fontResolver.addFont("Fonts/SimSun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

renderer.setDocumentFromString(html);

// 解决图片的相对路径问题

//renderer.getSharedContext().setBaseURL("file:D:/");

renderer.layout();

renderer.createPDF(os);

} catch (DocumentException | IOException e) {

e.printStackTrace();

} finally {

if (os != null) {

try {

os.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

以下基本上就可以进行测试了。

还有一些bug,其中一个就是图片出现在换页的位置就会被截断,暂时没有找到处理的方法,如下:

6461fba39f7dbab02c9d44f1508aa6e6

如果有人解决了,希望能在下方回复下解决方法,不胜感激。

java html转pdf 无法支持中文_java项目实现html转pdf的需求(支持中文和CSS样式)相关推荐

  1. java生成pdf不支持中文_java生成pdf以及解决中文中文乱码问题

    [在网上搜了一下iText的东东,简单的整理了一个Demo,解决了中文乱码问题,这里不贴链接了 网上搜一下就行了package com.westdream.test;import java.io.Fi ...

  2. java pdf模版的遍历_java使用itext操作填充pdf模板

    一.先创建pdf模板 1.先用word做出界面 image.png 2.再转换成pdf格式 image.png image.png 3.用Adobe Acrobat 打开你刚刚用word转换成的pdf ...

  3. lua 不支持中文字符_英雄联盟跳票?不支持中文?别急看这里!界面最强翻译!...

    大家期待英雄联盟手游已经很久了,16 号放出消息苦苦等待 28 号.老范跟大家的心情是一样的,注册拳头账号遇到种种问题,半天注册不成功等,要么就是卡在最后一步. 注册麻烦就不用说了,约定好的日子就跳票 ...

  4. java jsoup html_使用JAVA中的JSOUP从HTML中提取CSS样式

    如果样式嵌入在Element中,则只需使用.attr("style"). JSoup不是Html渲染器,它只是一个HTML解析器,因此您必须从检索到的< style>中 ...

  5. 在Unix/Linux上令(java)JVM支持中文输出

    在Unix/Linux上令(java)JVM支持中文输出 一.在Unix/Linux上令JVM支持中文输出 如 果用户使用的是UNIX的远程服务器,就会遇到中文字体在图像中输出的问题,特别是由于许多管 ...

  6. Flying Saucer 不支持中文,换行,粗体,CheckBox多选框的解决方案

    最近要生成打印版的保单信息,内容比较多,也比较复杂,iText直接生成的话,想必花很多时间,而且可能也很难维护,偶然看到了HTML 在 Fly Saucer的帮助下能转换成PDF,解析CSS还不错,顿 ...

  7. opencv中的imread不支持中文路径的解决办法

    其实严格来说,不是imread不支持中文路径,而是不支持non-ascii.所以不论路径如何转换编码格式,应该都不能解决问题. 解决的思路就是先用其他支持中文的API,把图片数据导入到内存中,然后通过 ...

  8. php json支持中文,php json 支持中文

    支持中文的 php json 函数 /************************************************************** * *使用特定function对数组 ...

  9. c语言添加输入函数吗,C语言scanf()函数下支持中文输入吗?

    C语言scanf()函数下支持中文输入吗? C语言scanf()函数下支持中文输入吗? 如果我编写一个程序,要求是先输入姓,再输入名,然后按照常姓名的方式排列出来,如果我需要输入中文该怎么办? 搜索更 ...

最新文章

  1. markdown常用操作(特殊字符显示、换行、字体颜色和大小、图片位置和大小)
  2. (转载)机器学习知识点(十一)隐马尔可夫模型
  3. Android IPC机制(五)用Socket实现跨进程聊天程序
  4. 这不是商业互吹,是学习的宝藏
  5. 中国制造强在哪儿?从美特斯邦威到Shein
  6. 计算机网络学习笔记(7. 报文交换与分组交换①)
  7. ssh GSSAPIAuthentication 参数
  8. java编写万年历的报告,用java编写的万年历代码
  9. 安卓 MediaRecorder 音频录制效果很差 模糊解决
  10. Struts1 页面提交到ActionForm,form为null
  11. 【c++NOIP2015 普及组】 推销员
  12. 关于匿名者组织(Anonymous),你都知道哪些?
  13. 基础算法学习大纲(附加yxc大佬算法模板)
  14. MATLAB 中nargin函数
  15. HDLBits Lemmings1-4
  16. 学习【Cesium】第六篇,Cesium地图点云与地形的加载(学不会揍我)
  17. 一个小公司老板的日常管理
  18. 北京2008福娃2图标
  19. “兼并”还是“合作” 宏碁方正各怀鬼胎
  20. 【云安全】云计算中常见的网络虚拟化

热门文章

  1. 微信退款API证书-P12、本地测试及Windows、Linux系统配置证书
  2. 微信小程序中object类型数据的访问和赋值
  3. 抖音怎么推广自己的作品,学会这四点,让你的视频轻松上热门
  4. 【Linux】网络基础(1)
  5. notepad++ PoorMansTSQLFormatter 插件安装
  6. 有情怀的格子布局(类似锤子桌面布局源码)
  7. 5款轻量、免费、无广的电脑软件,人民日报的朋友也在用
  8. mac OSX安装redmine及管理员账号的设置
  9. 场景生成及编辑3D定位论文阅读
  10. 坐拥两条黄金赛道,爱博医疗未来必是星辰大海!