HTML文件模板替換到轉換PDF文件並下載PDF文件

話不多說了,由於最近有通過數據生成PDF的需求,所以做完後在這裏記錄分享一下。直接用iText創建pdf文件考慮到html中的表格等等要合併或者什麼的太麻煩,就直接通過Html模板替換之後再轉換PDF來的更簡單。具體實現直接分享代碼給大家,高手勿噴!哈哈!

1.html文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
body {
	font-family: SimSun;
	font-size: 14px;
}

table {
	border-collapse: collapse;
	border: 1px solid #999;
	border-width: 1px 0 0 1px;
	width: 650px;
	height: auto;
}

table th {
	border: 1px solid #999;
	border-width: 0 1px 1px 0;
	padding: 2px;
	height: 50px;
	font-weight: bold;
	font-size: 23px;
}

table td {
	border: 1px solid #999;
	border-width: 0 1px 1px 0;
	padding: 2px;
	height: 40px;
}

.hfont {
	font-weight: bold;
	font-size: 18px;
}

.cheight {
	height: 320px;
}

.fheight {
	height: 60px;
}
</style>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"></meta>
</head>
<body>
    <table>
    	<tr>
    		<th align="center" colspan="4">HTML模板替換並轉換PDF文件</th>
    	</tr>
    	<tr>
    		<td class="hfont" width="20%" align="center" rowspan="4">基本信息</td>
    		<td align="left">姓名:###name###</td>
    	</tr>
    	<tr>
    		<td align="left">年齡:###age###</td>
    	</tr>
    	<tr>
    		<td align="left">性別:###sex###</td>
    	</tr>
    	<tr>
    		<td align="left">手機:###phone###</td>
    	</tr>
    </table>
  </body>
</html>
2.java工具類

package com.shangmai.tobacco.util;
  
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

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

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;
import com.shangmai.tobacco.common.DateUtils;

/**
 * Html模板替換並轉PDF文件-下載PDF
 * @author cavancao
 * 2015-09-24
 */
public class Html2PdfUtil{
	private static final String FONTPATH = "C:/WINDOWS/Fonts/SIMSUN.TTC";//支持中文字體(放哪裏都行)
	/**
	 * 定義各個模板內需要替換的參數
	 */
	// 通用表格導出
	private static final String[] USER_PDF = { "name", "age", "sex", "phone" };
	
	/**
	 * 通過參數獲取對應的屬性數組進行文本替換
	 */
	public static String[] findAttributes(String attributeKey) {
		if (attributeKey.equals("USER_PDF")) {
			return USER_PDF;
		} else {
			return new String[]{};
		}
	}
	
	/**
     * html轉換pdf文件
     * 注:支持中文,目前iText只支持上面FONTPATH定義的這種字體,所以html文件中也需要用樣式設置字體爲:SimSun
     * htmlPath 需要轉換的html源文件
     * pdfPath 轉換後pdf文件存放地址
     */
	public static String html2Pdf(String htmlPath, String pdfPath) {
		try {
			String url = new File(htmlPath).toURI().toURL().toString();
			OutputStream output = new FileOutputStream(pdfPath);
			ITextRenderer renderer = new ITextRenderer();
			renderer.setDocument(url);
			
			//解決中文支持問題(html的中文必須用SimSun字體,Java只能支持這1種字體)
			ITextFontResolver fontResolver = renderer.getFontResolver();
			fontResolver.addFont(FONTPATH, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			renderer.layout();
			renderer.createPDF(output);
			output.close();
			//刪除模板替換生成的新html文件
			File htmlFile = new File(htmlPath);
			if(htmlFile.exists()){
				htmlFile.delete();
			}
			return pdfPath;
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return null;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (DocumentException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 通過html模板替換特定字符生成新的html文件
	 * @param htmlPath html文件地址
	 * @param targetPath 替換模板生成新html的存放地址
	 * @param data 替換的數據
	 * @param attributeKey 獲取替換文本列表的數組標識
	 * @return
	 */
	public static String createHtml(String htmlPath, String targetPath,
			Map<String, String> data, String attributeKey) {

		StringBuffer sb = new StringBuffer();
		BufferedReader br = null;
		try {
			// 讀取html文件模板內容
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					new File(htmlPath)), "UTF-8"));
			String temp = "";
			while (null != (temp = br.readLine())) {
				sb.append(temp);
			}
			String htmlContext = sb.toString();
			// 替換html模板內的指定字符
			for (String attribute : findAttributes(attributeKey)) {
				htmlContext = htmlContext.replaceAll("###" + attribute + "###",
						data.get(attribute));
			}
			// 寫入新的html文件
			targetPath = targetPath + DateUtils.formatDate(new Date(), "yyyyMMddHHmmsss") + ".html";
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(new File(targetPath)), "UTF-8"));
			bw.write(htmlContext);
			bw.flush();
			bw.close();
			return targetPath;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 文件下載-支持中文名稱
	 * @param sourcePath下載文件全路徑(D:/test.pdf)
	 * @param fileName需要生成的下載文件名(HTML轉PDF測試.pdf)
	 * @param response
	 */
	public static void downloadFile(String sourcePath, String fileName,
			HttpServletResponse response) {
		// 讀到流中
		InputStream inStream = null;
		try {
			inStream = new FileInputStream(sourcePath);// 文件的存放路徑
			// 設置輸出的格式
			response.reset();
			String name = new String((fileName));
			response.addHeader("Content-Disposition", "attachment; filename=\""
					+ toUtf8String(name) + "\"");
			// 循環取出流中的數據
			byte[] b = new byte[100];
			int len;
			
			while ((len = inStream.read(b)) > 0) {
				response.getOutputStream().write(b, 0, len);
			}
			response.getOutputStream().flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				inStream.close();
				response.getOutputStream().close();
				//刪除源文件
				File sourceFile = new File(sourcePath);
				if(sourceFile.exists()){
					sourceFile.delete();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 下載中文名文件進行編碼轉換
	 */
	public static String toUtf8String(String s) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c >= 0 && c <= 255) {
				sb.append(c);
			} else {
				byte[] b;
				try {
					b = Character.toString(c).getBytes("utf-8");
				} catch (Exception ex) {
					b = new byte[0];
				}
				for (int j = 0; j < b.length; j++) {
					int k = b[j];
					if (k < 0)
						k += 256;
					sb.append("%" + Integer.toHexString(k).toUpperCase());
				}
			}
		}
		return sb.toString();
	}
	
	public static void main(String[] args){
		//map中put的key要和上面定義的USER_PDF數組一致
		Map<String,String> data = new HashMap<String,String>();
		//在html文件中必須爲###name###纔會被map中的name替換
		data.put("name", "王小二");
		data.put("age", "20");
		data.put("sex", "男");
		data.put("phone", "13800000000");
		String html = createHtml("D:/test.html", "D:/", data, "USER_PDF");
		String pdf = html2Pdf(html, "D:/"+DateUtils.formatDate(new Date(), "yyyyMMddHHmmsss")+".pdf");
		
		//如果在控制類有response對象可以直接轉換後的pdf文件,在控制類方法需要return null
		//downloadFile(pdf, "我的PDF文件.pdf", response);
		//return null;
		
		System.out.println("create html success! 文件存放路徑:" + pdf);
	}
}

3.相關支持文件(自行下載吧,我竟然不會上傳!第1次寫博客):2個jar包;1箇中文字體

iText-2.0.8.jar.jar

core-renderer.jar.jar


simsun.ttc 宋體(如果電腦裏沒有就去下載一個)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章