Java解决Itext pdf中文不显示问题

最近在项目需要,需要将html内容转换成pdf的文件,采用itextpdf总是不显示中文。
找了很多方法都没搞定,然后在网上看到了有个帖子说改源码解决这个问题,但是经过测试还是没有搞定。
并且个人不建议改源码,然后自己研究源码,借鉴了他的思路,可以不用改源码即可解决中文问题。

第一部:
maven 引入依赖的jar包

<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.9</version>
</dependency>

<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.9</version>
</dependency>

<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>



根据ChunkCssApplier重写apply方法

@SuppressWarnings("deprecation")
public class MyChunkCssApplier extends ChunkCssApplier {

public static BaseFont chinessFont = null;
static {
try {
// 中文支持,需要引入 itext-asian.jar
chinessFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 判断是否存在中文
* @param str
* @return
*/
private static boolean isChinese(String str){
if(str == null ){
return false;
}
//存在中文
String regex = ".*[\\u4e00-\\u9faf].*";
return Pattern.matches(regex, str);
}

/**
*
* 重写apply方法
*/
@Override
public Chunk apply(Chunk c, Tag t) {
Font f = applyFontStyles(t);
// 增加此段代码 如果中文 ,则返回中文字体
if (null != chinessFont && isChinese(c.getContent())) {
f = new Font(chinessFont, f.getSize(), f.getStyle(), f.getColor());
}
// 下面代码从源码中copy
float size = f.getSize();
Map<String, String> rules = t.getCSS();
for (Entry<String, String> entry : rules.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (CSS.Property.FONT_STYLE.equalsIgnoreCase(key)) {
if (value.equalsIgnoreCase(CSS.Value.OBLIQUE)) {
c.setSkew(0, 12);
}
} else if (CSS.Property.LETTER_SPACING.equalsIgnoreCase(key)) {
String letterSpacing = rules.get(CSS.Property.LETTER_SPACING);
float letterSpacingValue = 0f;
if (utils.isRelativeValue(value)) {
letterSpacingValue = utils.parseRelativeValue(letterSpacing, f.getSize());
} else if (utils.isMetricValue(value)){
letterSpacingValue = utils.parsePxInCmMmPcToPt(letterSpacing);
}
c.setCharacterSpacing(letterSpacingValue);
} else if (null != rules.get(CSS.Property.XFA_FONT_HORIZONTAL_SCALE)) { // only % allowed; need a catch block NumberFormatExc?
c.setHorizontalScaling(Float.parseFloat(rules.get(CSS.Property.XFA_FONT_HORIZONTAL_SCALE).replace("%", "")) / 100);
}
}
// following styles are separate from the for each loop, because they are based on font settings like size.
if (null != rules.get(CSS.Property.VERTICAL_ALIGN)) {
String value = rules.get(CSS.Property.VERTICAL_ALIGN);
if (value.equalsIgnoreCase(CSS.Value.SUPER) || value.equalsIgnoreCase(CSS.Value.TOP) || value.equalsIgnoreCase(CSS.Value.TEXT_TOP)) {
c.setTextRise((float) (size / 2 + 0.5));
} else if (value.equalsIgnoreCase(CSS.Value.SUB) || value.equalsIgnoreCase(CSS.Value.BOTTOM) || value.equalsIgnoreCase(CSS.Value.TEXT_BOTTOM)) {
c.setTextRise(-size / 2);
} else {
c.setTextRise(utils.parsePxInCmMmPcToPt(value));
}
}
String xfaVertScale = rules.get(CSS.Property.XFA_FONT_VERTICAL_SCALE);
if (null != xfaVertScale) {
if (xfaVertScale.contains("%")) {
size *= Float.parseFloat(xfaVertScale.replace("%", "")) / 100;
c.setHorizontalScaling(100 / Float.parseFloat(xfaVertScale.replace("%", "")));
}
}
if (null != rules.get(CSS.Property.TEXT_DECORATION)) {
String[] splitValues = rules.get(CSS.Property.TEXT_DECORATION).split("\\s+");
for (String value : splitValues) {
if (CSS.Value.UNDERLINE.equalsIgnoreCase(value)) {
c.setUnderline(null, 0.75f, 0, 0, -0.125f, PdfContentByte.LINE_CAP_BUTT);
}
if (CSS.Value.LINE_THROUGH.equalsIgnoreCase(value)) {
c.setUnderline(null, 0.75f, 0, 0, 0.25f, PdfContentByte.LINE_CAP_BUTT);
}
}
}
if (null != rules.get(CSS.Property.BACKGROUND_COLOR)) {
c.setBackground(HtmlUtilities.decodeColor(rules.get(CSS.Property.BACKGROUND_COLOR)));
}
f.setSize(size);
c.setFont(f);

Float leading = null;
if(rules.get(CSS.Property.LINE_HEIGHT) != null) {
String value = rules.get(CSS.Property.LINE_HEIGHT);
if(utils.isNumericValue(value)) {
leading = Float.parseFloat(value) * c.getFont().getSize();
} else if (utils.isRelativeValue(value)) {
leading = utils.parseRelativeValue(value, c.getFont().getSize());
} else if (utils.isMetricValue(value)){
leading = utils.parsePxInCmMmPcToPt(value);
}
}

if (leading != null) {
c.setLineHeight(leading);
}
return c;
}
}



新增一个ParserHTML.java


/**
* Hello world!
*
*/
public class ParserHTML
{

public static final String HTML = "D:/test/hero.html";
public static final String DEST = "D:/test/hero.pdf";
// public static final String HTML = "resources/xml/hero2.html";
// public static final String DEST = "results/xmlworker/asian2.pdf";

/**
* Creates a PDF with the words "Hello World"
* @param file
* @throws IOException
* @throws DocumentException
*/
public void createPdf(String file) throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
// step 3
document.open();
// step 4
// CSS
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream("body {font-family:tsc fming s tt}".getBytes()));
cssResolver.addCss(cssFile);

// 将ChunkCssApplier 设置为自定义的
CssAppliers cssAppliers = new CssAppliersImpl();
cssAppliers.setChunkCssAplier(new MyChunkCssApplier());
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));
// step 5
document.close();
}
/**
* Main method
*/
public static void main(String[] args) throws IOException, DocumentException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new ParserHTML().createPdf(DEST);
}
}




模板 hero.html

<p><span style="font-size:12.0pt; font-family:MS Mincho; color:red">長空abc</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Broken Sword),</span>
<span style="font-size:12.0pt; font-family:MS Mincho">秦王殘劍</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Flying Snow),</span>
<span style="font-size:12.0pt; font-family:MS Mincho">飛雪</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Moon), </span>
<span style="font-size:12.0pt; font-family:MS Mincho">如月</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(the King), and</span>
<span style="font-size:12.0pt; font-family:MS Mincho">秦王</span>
<span style="font-size:12.0pt; font-family:Times New Roman,serif">(Sky).</span></p>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值