itextpdf 實現html轉pdf中中文及圖片base64的解決方法:css
1. 中文解決方案: html
實現FontProvider接口:java
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顯示問題解決:app
實現com.itextpdf.tool.xml.html.Image類ide
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. 轉換方法:this
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框等的顯示還沒實現,待完善url