如何用iText高效处理大体积HTML转PDF(2MB/6-7MB场景)
iText HTML转PDF性能优化方案(针对大文件场景)
通用性能优化措施
- 精简ConverterProperties配置
- 关闭不必要的自动功能:禁用自动字体探测(若HTML使用已知字体),设置
converterProperties.setFontProvider(new DefaultFontProvider(false, false, false))减少字体扫描开销;指定媒体类型为打印converterProperties.setMediaDeviceDescription(new MediaDeviceDescription(MediaType.PRINT)),避免多余的媒体适配逻辑。 - 明确字符集:设置
converterProperties.setCharset(StandardCharsets.UTF_8.name()),省去编码自动探测的耗时。
- 关闭不必要的自动功能:禁用自动字体探测(若HTML使用已知字体),设置
- 优化IO操作
- 使用带缓冲区的流:替换直接的
FileInputStream/FileOutputStream为BufferedInputStream和BufferedOutputStream,降低磁盘IO的频繁调用:try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(htmlSource)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pdfDest))) { HtmlConverter.convertToPdf(bis, bos, converterProperties); } - 直接传入文件对象:优先使用
HtmlConverter.convertToPdf(htmlSource, pdfDest, converterProperties),iText对文件路径的处理有内置优化,比流处理更高效。
- 使用带缓冲区的流:替换直接的
- 字体预处理
- 预加载所需字体:提前添加常用字体到
FontProvider,避免转换过程中反复读取字体文件:DefaultFontProvider fontProvider = new DefaultFontProvider(); fontProvider.addFont("/path/to/your/regular-font.ttf"); converterProperties.setFontProvider(fontProvider); - 优先使用PDF内置字体:如Helvetica、Times Roman,减少字体嵌入的时间和PDF体积。
- 预加载所需字体:提前添加常用字体到
针对6-7MB大HTML文件的专项处理
- 分段转换+PDF合并
- 将大HTML拆分为多个独立片段(按章节、分页标记拆分),逐个转换为小PDF后用
PdfMerger合并,降低单次转换的内存压力:List<File> splitHtmlFiles = Arrays.asList(new File("part1.html"), new File("part2.html")); try (PdfWriter writer = new PdfWriter("merged_output.pdf"); PdfDocument mergedPdf = new PdfDocument(writer)) { PdfMerger merger = new PdfMerger(mergedPdf); ConverterProperties props = new ConverterProperties(); props.setMemorySavingMode(true); for (File htmlPart : splitHtmlFiles) { ByteArrayOutputStream tempStream = new ByteArrayOutputStream(); try (PdfDocument tempPdf = new PdfDocument(new PdfWriter(tempStream))) { HtmlConverter.convertToPdf(new FileInputStream(htmlPart), tempPdf, props); } try (PdfDocument tempPdfToMerge = new PdfDocument(new PdfReader(new ByteArrayInputStream(tempStream.toByteArray())))) { merger.merge(tempPdfToMerge, 1, tempPdfToMerge.getNumberOfPages()); } } }
- 将大HTML拆分为多个独立片段(按章节、分页标记拆分),逐个转换为小PDF后用
- 启用内存节省模式
- 在
ConverterProperties中开启内存优化:converterProperties.setMemorySavingMode(true),iText会采用流式处理策略,减少内存占用。
- 在
- 调整JVM堆内存
- 增大JVM堆内存参数(如
-Xmx4G,根据服务器配置调整),避免大文件转换时因内存不足导致频繁GC拖慢速度。
- 增大JVM堆内存参数(如
优化后的完整示例代码
import com.itextpdf.html2pdf.ConverterProperties; import com.itextpdf.html2pdf.HtmlConverter; import com.itextpdf.html2pdf.font.DefaultFontProvider; import com.itextpdf.html2pdf.media.MediaDeviceDescription; import com.itextpdf.html2pdf.media.MediaType; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfMerger; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.PdfWriter; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; public class LargeHtmlToPdf { public static void main(String[] args) throws IOException { // 单大文件优化转换 File htmlSource = new File("input.html"); File pdfDest = new File("output.pdf"); ConverterProperties converterProperties = new ConverterProperties(); converterProperties.setMemorySavingMode(true); converterProperties.setCharset(StandardCharsets.UTF_8.name()); converterProperties.setMediaDeviceDescription(new MediaDeviceDescription(MediaType.PRINT)); DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false); fontProvider.addStandardPdfFonts(); converterProperties.setFontProvider(fontProvider); try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(htmlSource)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pdfDest))) { HtmlConverter.convertToPdf(bis, bos, converterProperties); } // 超大型文件分段转换合并 List<File> splitHtmlParts = Arrays.asList(new File("part1.html"), new File("part2.html")); try (PdfWriter mergedWriter = new PdfWriter("merged_output.pdf"); PdfDocument mergedPdf = new PdfDocument(mergedWriter)) { PdfMerger merger = new PdfMerger(mergedPdf); ConverterProperties partProps = new ConverterProperties(); partProps.setMemorySavingMode(true); partProps.setFontProvider(fontProvider); for (File part : splitHtmlParts) { ByteArrayOutputStream tempBaos = new ByteArrayOutputStream(); try (PdfDocument tempPdf = new PdfDocument(new PdfWriter(tempBaos))) { HtmlConverter.convertToPdf(new FileInputStream(part), tempPdf, partProps); } try (PdfDocument tempPdfToMerge = new PdfDocument(new PdfReader(new ByteArrayInputStream(tempBaos.toByteArray())))) { merger.merge(tempPdfToMerge, 1, tempPdfToMerge.getNumberOfPages()); } } } } }
内容的提问来源于stack exchange,提问作者Akshay Kumar
相关产品推荐
相关产品推荐

