You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PDFBox Java的大体积合并PDF无损压缩方案及替代库咨询

解决PDFBox合并后大体积PDF的高效无损压缩问题

我之前帮朋友处理过类似的批量PDF合并压缩问题,老版本PDFBox的addCompression()被废弃确实让人头疼。下面给你分享当前版本PDFBox的正确压缩方案,以及几个靠谱的非商业替代类库:

一、PDFBox当前版本的高效无损压缩方案

原来的addCompression()方法被移除后,我们需要针对性地处理页面内容流和图像资源(这才是大体积PDF的核心元凶),以下是可直接复用的代码:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.save.SaveOptions;

import java.io.File;
import java.io.IOException;

public class PdfCompressor {
    public static void main(String[] args) throws IOException {
        PDDocument document = PDDocument.load(new File("c:/Temp/Merged.pdf"));

        // 遍历所有页面,压缩内容流+优化图像
        for (PDPage page : document.getPages()) {
            PDResources resources = page.getResources();
            
            // 压缩页面内容流
            PDStream contentStream = page.getContents();
            if (contentStream != null) {
                page.setContents(contentStream.createInputStream(COSName.FLATE_DECODE), true);
            }

            // 处理图像资源:给未压缩的图像添加Flate无损压缩
            for (COSName name : resources.getXObjectNames()) {
                PDXObject xobject = resources.getXObject(name);
                if (xobject instanceof PDImageXObject) {
                    PDImageXObject image = (PDImageXObject) xobject;
                    // 仅对未压缩的图像进行处理,避免重复压缩
                    if (image.getCOSObject().getDictionaryObject(COSName.FILTER) == null) {
                        image.setCompression(COSName.FLATE_DECODE);
                    }
                    // 可选:如果对画质要求不是极致,可降低分辨率(比如从600dpi降到300dpi,肉眼无差异)
                    // image.setResolution(300);
                }
            }
        }

        // 保存时启用全压缩模式,压缩元数据等冗余内容
        document.save(new File("C:/Temp/Compressed.pdf"), SaveOptions.builder().useFullCompression().build());
        document.close();
    }
}

这段代码的核心优势:

  • 对页面内容流启用Flate无损压缩,不损失任何文本、排版信息
  • 自动识别未压缩的图像资源并添加无损压缩,直击PDF体积过大的核心原因
  • 保存时启用全压缩模式,进一步压缩元数据等冗余内容

二、非商业替代类库推荐

如果觉得PDFBox的压缩逻辑不够灵活,这两个非商业类库值得一试:

1. iText 7 Community Edition

这是Java生态中最成熟的PDF处理库之一,非商业使用完全免费,压缩API更直观,对图像的优化选项也更丰富(比如支持批量调整图像质量、分辨率,自动移除冗余资源等)。示例代码片段:

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.ImageCompressor;
import com.itextpdf.kernel.pdf.PdfResourceManager;

import java.io.IOException;

public class ItextCompressor {
    public static void main(String[] args) throws IOException {
        PdfReader reader = new PdfReader("c:/Temp/Merged.pdf");
        // 启用全压缩模式
        PdfWriter writer = new PdfWriter("C:/Temp/Compressed.pdf", new WriterProperties().setFullCompressionMode(true));
        PdfDocument pdfDoc = new PdfDocument(reader, writer);

        // 遍历页面压缩图像
        PdfResourceManager resourceManager = new PdfResourceManager(pdfDoc);
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfCanvasProcessor processor = new PdfCanvasProcessor(new ImageCompressor(resourceManager, pdfDoc.getPage(i)));
            processor.processPageContent(pdfDoc.getPage(i));
        }

        pdfDoc.close();
        reader.close();
        writer.close();
    }
}

2. Ghostscript

虽然它是命令行工具,但可以通过Java调用命令实现批量压缩,非商业使用免费,压缩效果非常出色(尤其是图像密集型PDF)。你可以通过参数精准控制压缩级别,比如:

# 打印级压缩(几乎无损,体积大幅减小)
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.7 -dPDFSETTINGS=/printer -o C:/Temp/Compressed.pdf c:/Temp/Merged.pdf

参数说明:

  • /screen:屏幕级(低分辨率,最小体积)
  • /ebook:电子书级(适中分辨率)
  • /printer:打印级(接近无损)
  • /prepress:预印级(完全无损)

内容的提问来源于stack exchange,提问作者Quant74

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:27