iText将水印添加到所选页面

时间:2015-02-02 22:43:50

标签: java itext

我需要为每个具有特定文字的页面添加水印,例如" PROCEDURE DELETED"。

基于Bruno Lowagie在Adding watermark directly to the stream

中提出的建议

到目前为止,PdfWatermark类具有:

protected Phrase watermark = new Phrase("DELETED", new Font(FontFamily.HELVETICA, 60, Font.NORMAL, BaseColor.PINK));
ArrayList<Integer> arrPages = new ArrayList<Integer>();
boolean pdfChecked = false;

@Override
public void onEndPage(PdfWriter writer, Document document) {

    if(pdfChecked == false) {
        detectPages(writer, document);
        pdfChecked = true;
    } 
    int pageNum = writer.getPageNumber();

    if(arrPages.contains(pageNum)) {
        PdfContentByte canvas = writer.getDirectContentUnder();
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, watermark, 298, 421, 45);
    }
}

如果我在自定义detectPages方法中将数字3添加到arrPages ArrayList中,这样可以正常工作 - 它会在第3页显示所需的水印。

我遇到的问题是如何在文档中搜索我可以访问的文本字符串,只能从PdfWriter编写器或发送到onEndPage方法的com.itextpdf.text.Document文档中搜索。

这是我尝试过的,但未成功:

 private void detectPages(PdfWriter writer, Document document) {
    try {

        //arrPages.add(3);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, byteArrayOutputStream);
        //following code no work
        PdfReader reader = new PdfReader(writer.getDirectContent().getPdfDocument());
        PdfContentByte canvas = writer.getDirectContent();
        PdfImportedPage page;

        for (int i = 0; i < reader.getNumberOfPages(); ) {    
            page = writer.getImportedPage(reader, ++i);
            canvas.addTemplate(page, 1f, 0, 0.4f, 0.4f, 72, 50 * i);
            canvas.beginText();
            canvas.showTextAligned(Element.ALIGN_CENTER,

                    //search String
                    String.valueOf((char)(181 + i)), 496, 150 + 50 * i, 0);

                    //if(detected) arrPages.add(i);

            canvas.endText();
        }

我是否正确地将此作为解决方案,还是需要退出?

任何人都可以提供扫描文档所需的缺失链接并选择&#34;程序删除&#34;网页?

编辑:我使用的是iText 5.0.4 - 目前无法升级到5.5.X,但可能升级到以下的最新版本。

EDIT2:更多信息:这是向文档添​​加文本的方法(doc):

        String processed = processText(template);
        List<Element> objects = HTMLWorker.parseToListLog(new StringReader(processed),
                styles, interfaceProps, errors);
        for (Element elem : objects) {
            doc.add(elem);

        }

在我控制的addText方法中调用。 template只是来自数据库LOB的html。 processText会检查html中curlies包含的自定义标记,如${replaceMe}

这似乎是识别&#34; PROCEDURE DELETED&#34;生成文档时的字符串,但我没有看到Chunk.setGenericTags()的路径。

EDIT3:表难度

        List<Element> objects = HTMLWorker.parseToListLog(new StringReader(processed),
                styles, interfaceProps, errors);
        for (Element elem : objects) { 
            //Code below no work
            if (elem instanceof PdfPTable) {
                PdfPTable table = (PdfPTable) elem;
                ArrayList<Chunk> chks = table.getChunks();
                for(Chunk chk : chks){
                    if(chk.toString().contains("TEST DELETED")) {
                        chk.setGenericTag("delete_tag");
                    }
                }                       
            }

            doc.add(elem);
        }

评论员mlk和布鲁诺建议检测&#34; PROCEDURE DELETED&#34;关键字在添加到文档时。但是,由于关键字必然位于表中,因此必须通过PdfPTable而不是更简单的Element来检测它们。

我无法使用上面的代码。有关如何在表格单元格中查找文本并对其进行字符串比较的任何建议吗?

EDIT4:基于一些实验,我想做一些断言,请告诉我通过它们的方法:

  1. 需要使用Chunk.setGenericTag()来触发处理程序onGenericTag
  2. 由于某种原因,(PdfPTable) table.getChunks()不会返回块,至少我的系统会恢复。这是违反直觉的,可能存在导致此行为的设置,版本或代码错误。
  3. 因此,表格中的选择文本字符串不能用于触发水印。

1 个答案:

答案 0 :(得分:1)

感谢@mkl和@Bruno的所有帮助,我终于得到了一个可行的解决方案。任何有兴趣可以提供更优雅方法的人都会受到欢迎 - 肯定有空间。

在原始问题中给出的所有片段中都有两个课程。以下是体现工作解决方案的部分代码。

public class PdfExporter
    //a custom class to build content

    //create some content to add to pdf
    String text = "<div>Lots of important content here</div>";

    //assume the section is known to be deleted
    if(section_deleted) {
        //add a special marker to the text, in white-on-white
        text = "<span style=\"color:white;\">.!^DEL^?.</span>" + text + "</span>";
    } 

    //based on some indicator, we know we want to force a new page for a new section
    boolean ensureNewPage = true;

    //use an instance of PdfDocHandler to add the content
    pdfDocHandler.addText(text, ensureNewPage); 




public class PdfDocHandler extends PdfPageEventHelper
    private boolean isDEL;

    public boolean addText(String text, boolean ensureNewPage)

       if (ensureNewPage) {     
           //turn isDEL off: a forced pagebreak indicates a new section
           isDEL = false;
       }

        //attempt to find the special DELETE marker in first chunk
        //NOTE: this can be done several ways
        ArrayList<Chunk> chks = elem.getChunks();
        if(chks.size()>0) {
            if(chks.get(0).getContent().contains(".!^DEL^?.")) {
                //special delete marker found in text
                isDEL = true;
            }
        }

        //doc is an iText Document
        doc.add(elem);


    public void onEndPage(PdfWriter writer, Document document) {

        if(isDEL) {
            //set the watermark
            Phrase watermark = new Phrase("DELETED", new Font(Font.FontFamily.HELVETICA, 60, Font.NORMAL, BaseColor.PINK));
            PdfContentByte canvas = writer.getDirectContentUnder();
            ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, watermark, 298, 421, 45);   
        }
    }