java 利用itext将html转为pdf

Java项目需要将html转为pdf,在网上找了几个版本,转出来的效果都不理想:1、样式错乱     2、中文显示问题

最终自己找了个合适的版本:

package com.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.itextpdf.text.pdf.BaseFont;

public class htmlToPDF {
	public static void html2pdf(String htmlFile, String pdfFile) throws Exception {
		String url = new File(htmlFile).toURI().toURL().toString();
		System.out.println(url);
		// step 2
		OutputStream os = new FileOutputStream(pdfFile);
		ITextRenderer renderer = new ITextRenderer();
		renderer.setDocument(url);

		// step 3 解决中文支持
		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);
		}

		renderer.layout();
		renderer.createPDF(os);
		os.close();

		System.out.println("create pdf done!!");
	}

    //判断操作系统
	public static String getCurrentOperatingSystem() {
		String os = System.getProperty("os.name").toLowerCase();
		return os;
	}

	public static void main(String[] args) {
		String htmlFile = "C:/Users/Administrator/Desktop/1535075053000.html";
		String pdfFile = "D:/LOGS/dddd.pdf";
		try {
			htmlToPDF.html2pdf(htmlFile, pdfFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

以上代码在网络上找到的:参照地址给忘了

上面代码在转pdf的时候遇到:中文不显示,中文不换行

1、中文不展示:代码中指定的字体与html中字体不符;代码中为:simsun.ttc,所以在html的body标签中需添加style="font-family:SimSun;";其次html的标签一定要标准化,开头:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zh-cn" xmlns="http://www.w3.org/1999/xhtml">

内部标签一定要闭合,特别是:meta、br、img等

2、中文不换行:参照:http://downpour.iteye.com/blog/509417?page=3#comments

将flying-saucer-core-9.0.3.jar中的org.xhtmlrenderer.layout.Breaker类,添加了2个方法,修改了109行和121行,如下:

/* 
 * Breaker.java 
 * Copyright (c) 2004, 2005 Torbj�rn Gannholm,  
 * Copyright (c) 2005 Wisconsin Court System 
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser General Public License 
 * as published by the Free Software Foundation; either version 2.1 
 * of the License, or (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU Lesser General Public License for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 * 
 */  
package org.xhtmlrenderer.layout;  
  
import org.xhtmlrenderer.css.constants.IdentValue;  
import org.xhtmlrenderer.css.style.CalculatedStyle;  
import org.xhtmlrenderer.render.FSFont;  
  
/** 
 * A utility class that scans the text of a single inline box, looking for the  
 * next break point. 
 * @author Torbj�rn Gannholm 
 */  
public class Breaker {  
  
    public static void breakFirstLetter(LayoutContext c, LineBreakContext context,  
            int avail, CalculatedStyle style) {  
        FSFont font = style.getFSFont(c);  
        context.setEnd(getFirstLetterEnd(context.getMaster(), context.getStart()));  
        context.setWidth(c.getTextRenderer().getWidth(  
                c.getFontContext(), font, context.getCalculatedSubstring()));  
          
        if (context.getWidth() > avail) {  
            context.setNeedsNewLine(true);  
            context.setUnbreakable(true);  
        }  
    }  
      
    private static int getFirstLetterEnd(String text, int start) {  
        int i = start;  
        while (i < text.length()) {  
            char c = text.charAt(i);  
            int type = Character.getType(c);  
            if (type == Character.START_PUNCTUATION ||   
                    type == Character.END_PUNCTUATION ||  
                    type == Character.INITIAL_QUOTE_PUNCTUATION ||  
                    type == Character.FINAL_QUOTE_PUNCTUATION ||  
                    type == Character.OTHER_PUNCTUATION) {  
                i++;  
            } else {  
                break;  
            }  
        }  
        if (i < text.length()) {  
            i++;  
        }  
        return i;  
    }      
      
    public static void breakText(LayoutContext c,   
            LineBreakContext context, int avail, CalculatedStyle style) {  
        FSFont font = style.getFSFont(c);  
        IdentValue whitespace = style.getWhitespace();  
          
        // ====== handle nowrap  
        if (whitespace == IdentValue.NOWRAP) {  
            context.setEnd(context.getLast());  
            context.setWidth(c.getTextRenderer().getWidth(  
                    c.getFontContext(), font, context.getCalculatedSubstring()));  
            return;  
        }  
  
        //check if we should break on the next newline  
        if (whitespace == IdentValue.PRE ||  
                whitespace == IdentValue.PRE_WRAP ||  
                whitespace == IdentValue.PRE_LINE) {  
            int n = context.getStartSubstring().indexOf(WhitespaceStripper.EOL);  
            if (n > -1) {  
                context.setEnd(context.getStart() + n + 1);  
                context.setWidth(c.getTextRenderer().getWidth(  
                        c.getFontContext(), font, context.getCalculatedSubstring()));  
                context.setNeedsNewLine(true);  
                context.setEndsOnNL(true);  
            } else if (whitespace == IdentValue.PRE) {  
                context.setEnd(context.getLast());  
                context.setWidth(c.getTextRenderer().getWidth(  
                        c.getFontContext(), font, context.getCalculatedSubstring()));    
            }  
        }  
  
        //check if we may wrap  
        if (whitespace == IdentValue.PRE ||   
                (context.isNeedsNewLine() && context.getWidth() <= avail)) {  
            return;  
        }  
          
        context.setEndsOnNL(false);  
  
        String currentString = context.getStartSubstring();  
        int left = 0;  
//        int right = currentString.indexOf(WhitespaceStripper.SPACE, left + 1);  
        int right = getStrRight(currentString,left);  
        int lastWrap = 0;  
        int graphicsLength = 0;  
        int lastGraphicsLength = 0;  
  
        while (right > 0 && graphicsLength <= avail) {  
            lastGraphicsLength = graphicsLength;  
            graphicsLength += c.getTextRenderer().getWidth(  
                    c.getFontContext(), font, currentString.substring(left, right));  
            lastWrap = left;  
            left = right;  
//            right = currentString.indexOf(WhitespaceStripper.SPACE, left + 1);  
            right = getStrRight(currentString,left+1);  
        }  
  
        if (graphicsLength <= avail) {  
            //try for the last bit too!  
            lastWrap = left;  
            lastGraphicsLength = graphicsLength;  
            graphicsLength += c.getTextRenderer().getWidth(  
                    c.getFontContext(), font, currentString.substring(left));  
        }  
  
        if (graphicsLength <= avail) {  
            context.setWidth(graphicsLength);  
            context.setEnd(context.getMaster().length());  
            //It fit!  
            return;  
        }  
          
        context.setNeedsNewLine(true);  
  
        if (lastWrap != 0) {//found a place to wrap  
            context.setEnd(context.getStart() + lastWrap);  
            context.setWidth(lastGraphicsLength);  
        } else {//unbreakable string  
            if (left == 0) {  
                left = currentString.length();  
            }  
              
            context.setEnd(context.getStart() + left);  
            context.setUnbreakable(true);  
              
            if (left == currentString.length()) {  
                context.setWidth(c.getTextRenderer().getWidth(  
                        c.getFontContext(), font, context.getCalculatedSubstring()));  
            } else {  
                context.setWidth(graphicsLength);  
            }  
        }  
        return;  
    }  
  
    private static boolean isChinese(char c) {  
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);  
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS  
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS  
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A  
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION  
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION  
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {  
            return true;  
        }  
        return false;  
    }  
  
    private static int getStrRight(String s,int left){  
        if(left>=s.length())  
            return -1;  
        char[] ch = s.toCharArray();  
        for(int i = left;i<ch.length;i++){  
            if(isChinese(ch[i]) || ' ' == ch[i]){  
                return i==0?i+1:i;  
            }  
        }  
        return -1;  
    }  
  
}  

至此,终于能正常转换了;

猜你喜欢

转载自blog.csdn.net/woweipingzui/article/details/82017089