使用iTextPDF将HTML转PDF时遇图片错误如何跳过继续转换?
解决iTextPDF转换HTML到PDF时跳过错误图片的问题
这个问题我之前碰到过,核心思路就是接管图片加载的逻辑,在加载失败的时候自定义处理逻辑,而不是让整个转换流程崩溃。下面分两种主流iText版本给你具体方案:
方案一:iText 7 及以上版本(推荐)
iText7的HtmlConverter提供了扩展接口IImageProvider,我们可以通过实现这个接口来控制图片加载的异常处理:
1. 自定义图片加载处理器
创建一个实现IImageProvider的类,在getImage方法里捕获图片加载异常,返回占位图或者直接跳过(返回null):
import com.itextpdf.io.image.ImageDataFactory; import com.itextpdf.layout.element.Image; import com.itextpdf.html2pdf.resolver.resource.IImageProvider; import com.itextpdf.html2pdf.ConverterProperties; import java.io.IOException; class CustomImageProvider implements IImageProvider { @Override public Image getImage(String src, String baseUri, ConverterProperties converterProperties) { try { // 尝试加载原始图片 return new Image(ImageDataFactory.create(src)); } catch (IOException e) { e.printStackTrace(); // 可选:记录错误日志 // 方案1:返回一个本地占位图(推荐,用户能直观看到哪里有问题) try { return new Image(ImageDataFactory.create("path/to/your/placeholder.png")); } catch (IOException ex) { // 方案2:如果占位图也加载失败,返回null直接跳过该图片 return null; } } } }
2. 在转换时配置自定义处理器
把自定义的ImageProvider注入到ConverterProperties中,再传给转换方法:
import com.itextpdf.html2pdf.HtmlConverter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class HtmlToPdfConverter { public static void main(String[] args) throws IOException { String inputHtmlPath = "your-input.html"; String outputPdfPath = "your-output.pdf"; // 配置转换属性 ConverterProperties properties = new ConverterProperties(); properties.setImageProvider(new CustomImageProvider()); // 执行转换 HtmlConverter.convertToPdf( new FileInputStream(inputHtmlPath), new FileOutputStream(outputPdfPath), properties ); } }
方案二:iText 5.x 版本(旧版本兼容)
如果你还在使用iText5的XMLWorker来处理HTML,需要实现旧版的IImageProvider接口:
1. 自定义图片加载处理器
import com.itextpdf.text.Image; import com.itextpdf.tool.xml.html.ImageProvider; import java.io.IOException; class CustomImageProvider5 implements ImageProvider { @Override public Image retrieve(String src) { try { // 尝试加载原始图片 return Image.getInstance(src); } catch (Exception e) { e.printStackTrace(); // 记录错误日志 // 加载失败时返回占位图或null try { return Image.getInstance("path/to/your/placeholder.png"); } catch (Exception ex) { return null; } } } @Override public String getImageRootPath() { return null; // 不需要设置根路径的话返回null } }
2. 配置XMLWorker使用自定义处理器
import com.itextpdf.text.Document; import com.itextpdf.text.PageSize; import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.tool.xml.XMLWorkerHelper; import com.itextpdf.tool.xml.html.CssAppliers; import com.itextpdf.tool.xml.html.CssAppliersImpl; import com.itextpdf.tool.xml.html.HtmlPipelineContext; import com.itextpdf.tool.xml.pipeline.css.CssResolver; import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline; import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline; import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class HtmlToPdfConverter5 { public static void main(String[] args) throws IOException { Document document = new Document(PageSize.A4); String outputPdfPath = "your-output.pdf"; PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfPath)); document.open(); // 配置HTML处理上下文,注入自定义图片处理器 CssAppliers cssAppliers = new CssAppliersImpl(); HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers); htmlContext.setImageProvider(new CustomImageProvider5()); htmlContext.setTagFactory(com.itextpdf.tool.xml.html.Tags.getHtmlTagProcessorFactory()); // 构建处理管道 CssResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true); HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer)); CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline); // 执行转换 XMLWorkerHelper.getInstance().parseXHtml(writer, document, new FileInputStream("your-input.html"), cssPipeline); document.close(); } }
关键说明
- 如果返回
null,对应的<img>标签会被直接跳过,PDF中不会留下任何痕迹; - 返回占位图的话,能让用户清晰看到哪些图片加载失败,更利于排查问题;
- 不管哪个版本,核心都是把图片加载的异常捕获逻辑从全局转换流程中剥离出来,放到单独的图片处理器里,这样单个图片的失败就不会导致整个转换终止。
内容的提问来源于stack exchange,提问作者yasin tavukcuoglu
相关产品推荐
相关产品推荐

