用itext把html轉成pdf,帶圖片
很久以前使用itext轉換html到pdf過,但當時沒記錄,最近又有這種需求,一直沒想起來,現在做好了記錄一下
下面是虛擬碼:
依賴jar包及版本:
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.0.8</version>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R8</version>
注意事項:
1.html標籤必須成對,有對應的結束標籤,比如<meta/>或<meta></meta>
2.在樣式表中第一行加入@page{size:200mm 300mm;} 可以設定PDF寬高
3.該版本不支援CSS3,所以頁面中如果有CSS3的樣式寫法,可能需要修改成CSS2
4.html中必須設定中文字型樣式,否則中文無法正常顯示,比如:<body style = 'font-family:SimSun;'>,且字型樣式必須與下面程式碼中設定的一致,比如使用了C:/Windows/Fonts/simsun.ttc,則此處必須使用SimSun(區分大小寫)
-Html2Pdf.java-----------------------------------------------------------------------------------------------------------------------
OutputStream os = new FileOutputStream("PDF檔案輸出全路徑");
ITextRenderer renderer = new ITextRenderer();
// 圖片base64支援,把圖片轉換為itext自己的圖片物件
if(hasImage) {// 如果攜帶圖片則加上以下程式碼,將圖片標籤轉換為Itext自己的圖片物件
renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());
renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);
}
renderer.setDocumentFromString(html);
// 解決中文支援問題
ITextFontResolver fontResolver = renderer.getFontResolver();
// 字型設定,字型檔案路徑比如可以為C:/Windows/Fonts/simsun.ttc,也可以拷貝到其他目錄
fontResolver.addFont("字型檔案路徑", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// renderer.getSharedContext().setBaseURL("file:/D:/z/temp/"); // 如果img標籤中src是http或絕對地址可以不要本行程式碼,另外對於linux系統中寫法暫不確認應該是不需要file:/字首
renderer.layout();
renderer.createPDF(os);
os.close();
Base64ImgReplacedElementFactory.java:----------------------------------------------------------------------------------
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 e1) {
fsImage = null;
}
if (fsImage != null) {
// 對影象進行縮放
if (cssWidth != -1 || cssHeight != -1) {
fsImage.scale(cssWidth, cssHeight);
}
return new ITextImageElement(fsImage);
}
}
return null;
}
/**
* 編解碼base64並生成itext影象
*/
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;
}
public void reset() {}
@Override
public void remove(Element arg0) {}
@Override
public void setFormSubmissionListener(FormSubmissionListener arg0) {}
}
----------------------------------------------------------------------------------