itextpdf 实现html转pdf中中文及图片base64的解决方法:
1. 中文解决方案:
实现FontProvider接口:
package com.mumu.image2pdf;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontProvider;
import com.itextpdf.text.pdf.BaseFont;
public class MyFontProvider implements FontProvider {
private BaseColor bc;
private String fontname;
private String encoding;
private boolean embedded;
private boolean cached;
private float size;
private int style;
private BaseFont baseFont;
public MyFontProvider() {
}
public BaseColor getBc() {
return bc;
}
public void setBc(BaseColor bc) {
this.bc = bc;
}
public String getFontname() {
return fontname;
}
public void setFontname(String fontname) {
this.fontname = fontname;
}
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public boolean isEmbedded() {
return embedded;
}
public void setEmbedded(boolean embedded) {
this.embedded = embedded;
}
public boolean isCached() {
return cached;
}
public void setCached(boolean cached) {
this.cached = cached;
}
public float getSize() {
return size;
}
public void setSize(float size) {
this.size = size;
}
public int getStyle() {
return style;
}
public void setStyle(int style) {
this.style = style;
}
public BaseFont getBaseFont() {
return baseFont;
}
public void setBaseFont(BaseFont baseFont) {
this.baseFont = baseFont;
}
public MyFontProvider(BaseColor bc, String fontname, String encoding, boolean embedded, boolean cached, float size,
int style, BaseFont baseFont) {
super();
this.bc = bc;
this.fontname = fontname;
this.encoding = encoding;
this.embedded = embedded;
this.cached = cached;
this.size = size;
this.style = style;
this.baseFont = baseFont;
}
@Override
public Font getFont(String arg0, String arg1, boolean arg2, float arg3, int arg4, BaseColor arg5) {
Font font = null;
if (baseFont == null) {
font = new Font();
} else {
font = new Font(baseFont);
}
font.setColor(arg5);
font.setFamily(fontname);
font.setSize(size);
font.setStyle(arg4);
return font;
}
@Override
public boolean isRegistered(String arg0) {
// TODO Auto-generated method stub
return true;
}
}
2. 图片base64的dataurl显示问题解决:
实现com.itextpdf.tool.xml.html.Image类
package com.mumu.image2pdf;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.codec.Base64;
import com.itextpdf.tool.xml.NoCustomContextException;
import com.itextpdf.tool.xml.Tag;
import com.itextpdf.tool.xml.WorkerContext;
import com.itextpdf.tool.xml.exceptions.RuntimeWorkerException;
import com.itextpdf.tool.xml.html.HTML;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
public class ImageTagProcessor extends com.itextpdf.tool.xml.html.Image {
/*
* (non-Javadoc)
*
* @see com.itextpdf.tool.xml.TagProcessor#endElement(com.itextpdf.tool.xml.Tag, java.util.List, com.itextpdf.text.Document)
*/
@Override
public List<Element> end(final WorkerContext ctx, final Tag tag, final List<Element> currentContent) {
final Map<String, String> attributes = tag.getAttributes();
String src = attributes.get(HTML.Attribute.SRC);
List<Element> elements = new ArrayList<Element>(1);
if (null != src && src.length() > 0) {
Image img = null;
if (src.startsWith("data:image/")) {
final String base64Data = src.substring(src.indexOf(",") + 1);
try {
img = Image.getInstance(Base64.decode(base64Data));
} catch (Exception e) {
throw new I18NIllegalArgumentException(e);
}
if (img != null) {
try {
final HtmlPipelineContext htmlPipelineContext = getHtmlPipelineContext(ctx);
elements.add(getCssAppliers().apply(new Chunk((com.itextpdf.text.Image) getCssAppliers().apply(img, tag, htmlPipelineContext), 0, 0, true), tag,
htmlPipelineContext));
} catch (NoCustomContextException e) {
throw new RuntimeWorkerException(e);
}
}
}
if (img == null) {
elements = super.end(ctx, tag, currentContent);
}
}
return elements;
}
}
3. 转换方法:
public void html2pdf(String html, File file) throws I18NIllegalArgumentException {
try {
// step 1
Document document = new Document();
BaseFont bfChinese;
bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
MyFontProvider myFontProvider = new MyFontProvider(BaseColor.BLACK, "", "", false, false, 16, 1, bfChinese);
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
// step 3
document.open();
final TagProcessorFactory tagProcessorFactory = Tags.getHtmlTagProcessorFactory();
tagProcessorFactory.removeProcessor(HTML.Tag.IMG);
tagProcessorFactory.addProcessor(new ImageTagProcessor(), HTML.Tag.IMG);
final CssFilesImpl cssFiles = new CssFilesImpl();
cssFiles.add(XMLWorkerHelper.getInstance().getDefaultCSS());
final StyleAttrCSSResolver cssResolver = new StyleAttrCSSResolver(cssFiles);
final HtmlPipelineContext hpc = new HtmlPipelineContext(new CssAppliersImpl(myFontProvider));
hpc.setAcceptUnknown(true).autoBookmark(true).setTagFactory(tagProcessorFactory);
final HtmlPipeline htmlPipeline = new HtmlPipeline(hpc, new PdfWriterPipeline(document, writer));
final Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
final XMLWorker worker = new XMLWorker(pipeline, true);
final Charset charset = Charset.forName("UTF-8");
final XMLParser xmlParser = new XMLParser(true, worker, charset);
ByteArrayInputStream bais = new ByteArrayInputStream(html.getBytes("UTF-8"));
xmlParser.parse(bais, charset);
// step 5
document.close();
bais.close();
} catch (Exception e) {
throw new I18NIllegalArgumentException(e);
}
}
PS: input框等的显示还没实现,待完善