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>

猜你喜欢

转载自362217990.iteye.com/blog/2294877