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

使用PDFBox 2.0.24移除PDF二维码后文件变大且未删除求助

问题分析与修复方案

核心问题

  1. 二维码未成功移除:依赖XMP元数据的标题字段识别二维码,若图片无该元数据或标题不匹配,就无法识别;直接操作COS字典移除资源,未更新PDFBox的对象缓存,导致资源未真正删除。
  2. 文件体积暴涨:创建新文档时未继承原文档的压缩配置,重新生成的内容流和资源未启用压缩,原压缩内容被解压后写入新文档,导致体积大幅增大。

修复步骤

1. 修复二维码识别与移除逻辑

  • 替换资源移除方式:不要直接修改COS字典,使用PDFBox提供的PDResources.removeXObject()方法,确保更新对象缓存:
    // 替换原COS字典移除代码
    pdResources.removeXObject(propertyName);
    
  • 优化二维码识别方式:依赖XMP元数据不可靠,可通过ZXing库识别图片是否为二维码,或结合图片尺寸、格式等特征判断:
    // 示例:用ZXing识别二维码
    BufferedImage img = pdImageXObject.getImage();
    try {
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(img)));
        Result result = new MultiFormatReader().decode(bitmap);
        // 能解码出内容,判定为二维码
        pdResources.removeXObject(propertyName);
        qrCodeCosName = propertyName.getName();
        hasQRCodeOnPage = true;
    } catch (NotFoundException e) {
        // 不是二维码,跳过
    }
    

2. 解决文件体积增大问题

  • 启用文档压缩:保存文档时使用PDFSaveOptions开启内容流和图片压缩:
    PDFSaveOptions saveOptions = new PDFSaveOptions();
    saveOptions.setCompressContentStreams(true); // 压缩内容流
    saveOptions.setCompressImages(true); // 压缩图片
    saveOptions.setImageQuality(0.9f); // 可调整图片质量,平衡体积与清晰度
    newDocument.save(destPath, saveOptions);
    
  • 避免创建新文档:直接在原文档上修改页面,减少资源重复复制:
    // 原代码创建新文档改为直接操作原文档
    PDDocument pdDocument = PDDocument.load(new File(sourcePath));
    boolean hasModified = false;
    for (int i = 0; i < pdDocument.getNumberOfPages(); i++) {
        PDPage page = pdDocument.getPage(i);
        if (removeQRCodeImage(pdDocument, page, imgUniqueId + i)) {
            hasModified = true;
        }
    }
    if (hasModified) {
        PDFSaveOptions options = new PDFSaveOptions();
        options.setCompressContentStreams(true);
        options.setCompressImages(true);
        pdDocument.save(destPath, options);
    }
    pdDocument.close();
    

3. 完善内容流处理逻辑

确保完全移除所有引用二维码的Do操作:

// 遍历内容流token时,正确移除COSName和Do操作
for (int j = 0; j < tokens.size(); j++) {
    Object token = tokens.get(j);
    if (token instanceof Operator) {
        Operator op = (Operator) token;
        if ("Do".equals(op.getName())) {
            COSName cosName = (COSName) tokens.get(j - 1);
            if (cosName.getName().equals(qrCodeCosName)) {
                // 移除已添加的COSName
                if (!newTokens.isEmpty()) {
                    newTokens.remove(newTokens.size() - 1);
                }
                // 跳过当前Do操作,不添加到newTokens
                continue;
            }
        }
    }
    newTokens.add(token);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 18:05:29