Java 将包含PdfStamper图层的图层添加到PDF会展平现有图层

Java 将包含PdfStamper图层的图层添加到PDF会展平现有图层,java,pdf,itext,Java,Pdf,Itext,我为打印创建了PDF文件,其中包含一个不可打印的信纸背景层,所以它在打印和屏幕上看起来都一样 要找到的示例 现在,一旦准备好的PDF被批准打印,我想添加一个包含存档/批准数据的条形码-同样作为一个未打印的层 但一旦我这样做了,所有现有的图层都消失了,只剩下添加的图层,导致无法打印的背景图层突然被打印出来 有关我的(失败)结果,请参阅 以下是我的addBarcode方法: public static byte[] addBarcode_OriginalIdea(byte[] src, Strin

我为打印创建了PDF文件,其中包含一个不可打印的信纸背景层,所以它在打印和屏幕上看起来都一样

要找到的示例

现在,一旦准备好的PDF被批准打印,我想添加一个包含存档/批准数据的条形码-同样作为一个未打印的层

但一旦我这样做了,所有现有的图层都消失了,只剩下添加的图层,导致无法打印的背景图层突然被打印出来

有关我的(失败)结果,请参阅

以下是我的addBarcode方法:

public static byte[] addBarcode_OriginalIdea(byte[] src, String barcodeText, String layerName, boolean printable) {
    try (ByteArrayOutputStream bo = new ByteArrayOutputStream()) {
        PdfReader reader = new PdfReader(src);                      
        PdfStamper stamper = new PdfStamper(reader, bo);
        //Add an additional layer to Page 1
        PdfContentByte over = stamper.getOverContent(1);
        Barcode128 barcode = new Barcode128();
        barcode.setCode(barcodeText);
        barcode.setBarHeight(10f);                     
        Image img = barcode.createImageWithBarcode(over, Color.decode("#0c1754"), Color.decode("#0c1754"));
        img.setRotationDegrees(-90f);            
        img.setAbsolutePosition(reader.getPageSize(1).getRight()-img.getHeight()-5,  5);
        PdfLayer barcodeLayer = new PdfLayer(layerName, stamper.getWriter());
        barcodeLayer.setOnPanel(true);
        barcodeLayer.setPrint("Print", printable);
        over.beginLayer(barcodeLayer);
        over.addImage(img);
        over.endLayer();
        //End add layer
        stamper.close();
        bo.close();
        return bo.toByteArray();
    } catch (Exception e) {
        e.printStackTrace();
        return new byte[]{};
    }
}
困惑。那么接下来我尝试了什么

  • 删除代码以添加图层-保留压模零件 结果:层仍然存在

  • 在添加新图层之前和之后打印图层: 结果:我可以看到添加的新层,但PdfStamper在关闭期间抛出异常

  • 代码:

    public static byte[] addBarcode_showLayersBeforeAfter(byte[] src, String barcodeText, String layerName, boolean printable) {
        try (ByteArrayOutputStream bo = new ByteArrayOutputStream()) {
            PdfReader reader = new PdfReader(src);                      
            PdfStamper stamper = new PdfStamper(reader, bo);
            //List all layers contained in document before
            Map map = stamper.getPdfLayers();
            for(Object me: map.keySet()) {
                System.out.println("Layer before: " + me);
            }                       
    
            //Add an additional layer to Page 1
            PdfContentByte over = stamper.getOverContent(1);
            Barcode128 barcode = new Barcode128();
            barcode.setCode(barcodeText);
            barcode.setBarHeight(10f);                     
            Image img = barcode.createImageWithBarcode(over, Color.decode("#0c1754"), Color.decode("#0c1754"));
            img.setRotationDegrees(-90f);            
            img.setAbsolutePosition(reader.getPageSize(1).getRight()-img.getHeight()-5,  5);
            PdfLayer barcodeLayer = new PdfLayer(layerName, stamper.getWriter());
            barcodeLayer.setOnPanel(true);
            barcodeLayer.setPrint("Print", printable);
            over.beginLayer(barcodeLayer);
            over.addImage(img);
            over.endLayer();            
            //End add layer
    
            //List all layers contained in document before
            Map map2 = stamper.getPdfLayers();
            for(Object me: map2.keySet()) {
                System.out.println("Layer after: " + me);
            }
            reader.close();
            stamper.close(); // <-- this now throws an Exception!
            bo.close();
            return bo.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            return new byte[]{};
        }
    }
    
    我真的,真的很讨厌在这一点上重新创建整个PDF+条形码,只是为了把图层弄清楚,有人知道如何在PdfStamper(或其他方式)中添加另一个不可打印的图层,同时保留所有现有图层吗

    非常感谢你

    编辑

    在布鲁诺的建议下,移动到itext版本5,这变得更加奇怪。现在我可以看到该层被添加到PDF中。现在背景保持未打印(如需要),但添加的条形码层始终打印。添加条形码后,我使用此代码分析图层:

            Map map2 = stamper.getPdfLayers();
            for(Object me: map2.keySet()) {
                System.out.println("Layer after: " + me );
                PdfDictionary dict2 = ((PdfLayer)map2.get(me)).getAsDict(PdfName.USAGE);
                if(dict2 != null) {
                    PdfDictionary dict = dict2.getAsDict(PdfName.PRINT);
                    System.out.println("Subtype" + dict.getAsName(PdfName.SUBTYPE));
                    System.out.println("Printable: " + dict.getAsName(PdfName.PRINTSTATE));
                }
            }
    
    为添加的层生成以下结果:

    Printable: /OFF
    Layer after: StackLayer
    Subtype/Print
    
    但仍然-在点击打印预览时,图层仍然存在。现在,我使用了刚刚创建的pdf并列出了图层-打印属性消失了:

    Layer before: StackLayer
    Layer before: Template-Page-2
    

    因此,无论发生什么,似乎都是在关闭PdfStamper时发生的,比如没有正确更新PdfLayers之类。我想接下来我必须研究itext source:-(

    很抱歉,我要研究您的问题,因为我知道我可以解决这个问题(几年前我为一位客户解决了一个类似的问题),但后来我在你的堆栈跟踪中注意到了我的名字。这意味着你使用的iText版本至少可以追溯到2009年。如果你想避免挫折(你自己的挫折和我的一样),请升级和。你好,布鲁诺谢谢你的建议-可以,重新测试。好的,我可能无法立即回答后续问题。我摔断了胳膊,只能用一只手打字。我下周不应该工作(但很难按照医生的指示)。好了,布鲁诺!改为iTest 5.5.11(我工作的公司有许可证)解决了异常,但没有解决stamper中添加的条形码层始终被打印。@BrunoLowagie:我觉得这是itext pdfstamper中的一个缺陷-如果PDF中存在要打印的层,则某些OCG属性(如打印信息)似乎不会被合并。为了解决我的问题,我将条形码移到了PageEvent中,并将其添加到文档的第一页,即使这需要重新生成整个pdf。
    Layer before: StackLayer
    Layer before: Template-Page-2