使用 iText 某些 pdf 文件水印不显示

发布于 2024-10-21 19:54:44 字数 2553 浏览 5 评论 0原文

我们公司使用 iText 在一些 pdf 表格上标记一些水印文本(不是图像)。我注意到 95% 的表格可以正确显示水印,大约 5% 则不能。我测试了一下,复制了2个原始pdf文件,一个被标记为ok,另一个不ok,然后通过一个小程序进行测试,结果相同:一个被标记,另一个没有。然后我尝试了最新版本的 iText jar 文件(版本 5.0.6),同样的事情。我检查了 pdf 文件属性、安全设置等,似乎没有任何提示。执行程序后,结果文件确实更改了大小并标记为“由 iText 版本更改...”。

这里是水印示例代码(使用itext jar版本2.1.7),注意传入的topText,mainText,bottonText参数,使3行水印在pdf中显示为水印。

任何帮助表示赞赏!

public class WatermarkGenerator {

    private static int TEXT_TILT_ANGLE = 25;
    private static Color MEDIUM_GRAY = new Color(160, 160, 160);
    private static int SUPPORT_FONT_SIZE = 42;
    private static int PRIMARY_FONT_SIZE = 54;

    public static void addWaterMark(InputStream pdfInputStream,
        OutputStream outputStream, String topText, 
        String mainText, String bottomText) throws Exception {
        PdfReader reader = new PdfReader(pdfInputStream);
        int numPages = reader.getNumberOfPages();

        // Create a stamper that will copy the document to the output
        // stream.
        PdfStamper stamp = new PdfStamper(reader, outputStream);
        int page=1;

        BaseFont baseFont = 
            BaseFont.createFont(BaseFont.HELVETICA_BOLDOBLIQUE,
                BaseFont.WINANSI, BaseFont.EMBEDDED);

        float width;
        float height;

        while (page <= numPages) {
            PdfContentByte cb = stamp.getOverContent(page);
            height = reader.getPageSizeWithRotation(page).getHeight() / 2;
            width = reader.getPageSizeWithRotation(page).getWidth() / 2;

            cb = stamp.getUnderContent(page);
            cb.saveState();
            cb.setColorFill(MEDIUM_GRAY);

            // Top Text
            cb.beginText();
            cb.setFontAndSize(baseFont, SUPPORT_FONT_SIZE);
            cb.showTextAligned(Element.ALIGN_CENTER, topText, width,
                    height+PRIMARY_FONT_SIZE+16, TEXT_TILT_ANGLE);
            cb.endText();

            // Primary Text
            cb.beginText();
            cb.setFontAndSize(baseFont, PRIMARY_FONT_SIZE);
            cb.showTextAligned(Element.ALIGN_CENTER, mainText, width,
                    height, TEXT_TILT_ANGLE);
            cb.endText();

            // Bottom Text
            cb.beginText();
            cb.setFontAndSize(baseFont, SUPPORT_FONT_SIZE);
            cb.showTextAligned(Element.ALIGN_CENTER, bottomText, width,
                    height-PRIMARY_FONT_SIZE-6, TEXT_TILT_ANGLE);
            cb.endText();
            cb.restoreState();

            page++;
        }

        stamp.close();
    }
}

Our company using iText to stamp some watermark text (not image) on some pdf forms. I noticed 95% forms shows watermark correctly, about 5% does not. I tested, copy 2 original pdf files, one was marked ok, other one does not ok, then tested in via a small program, same result: one got marked, the other does not. I then tried the latest version of iText jar file (version 5.0.6), same thing. I checked pdf file properties, security settings etc, seems nothing shows any hint. The result file does changed size and markd "changed by iText version...." after executed program.

Here is the sample watermark code (using itext jar version 2.1.7), note topText, mainText, bottonText parameters passed in, make 3 lines of watermarks show in the pdf as watermark.

Any help appreciated !!

public class WatermarkGenerator {

    private static int TEXT_TILT_ANGLE = 25;
    private static Color MEDIUM_GRAY = new Color(160, 160, 160);
    private static int SUPPORT_FONT_SIZE = 42;
    private static int PRIMARY_FONT_SIZE = 54;

    public static void addWaterMark(InputStream pdfInputStream,
        OutputStream outputStream, String topText, 
        String mainText, String bottomText) throws Exception {
        PdfReader reader = new PdfReader(pdfInputStream);
        int numPages = reader.getNumberOfPages();

        // Create a stamper that will copy the document to the output
        // stream.
        PdfStamper stamp = new PdfStamper(reader, outputStream);
        int page=1;

        BaseFont baseFont = 
            BaseFont.createFont(BaseFont.HELVETICA_BOLDOBLIQUE,
                BaseFont.WINANSI, BaseFont.EMBEDDED);

        float width;
        float height;

        while (page <= numPages) {
            PdfContentByte cb = stamp.getOverContent(page);
            height = reader.getPageSizeWithRotation(page).getHeight() / 2;
            width = reader.getPageSizeWithRotation(page).getWidth() / 2;

            cb = stamp.getUnderContent(page);
            cb.saveState();
            cb.setColorFill(MEDIUM_GRAY);

            // Top Text
            cb.beginText();
            cb.setFontAndSize(baseFont, SUPPORT_FONT_SIZE);
            cb.showTextAligned(Element.ALIGN_CENTER, topText, width,
                    height+PRIMARY_FONT_SIZE+16, TEXT_TILT_ANGLE);
            cb.endText();

            // Primary Text
            cb.beginText();
            cb.setFontAndSize(baseFont, PRIMARY_FONT_SIZE);
            cb.showTextAligned(Element.ALIGN_CENTER, mainText, width,
                    height, TEXT_TILT_ANGLE);
            cb.endText();

            // Bottom Text
            cb.beginText();
            cb.setFontAndSize(baseFont, SUPPORT_FONT_SIZE);
            cb.showTextAligned(Element.ALIGN_CENTER, bottomText, width,
                    height-PRIMARY_FONT_SIZE-6, TEXT_TILT_ANGLE);
            cb.endText();
            cb.restoreState();

            page++;
        }

        stamp.close();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情痴 2024-10-28 19:54:44

我们通过更改 Adob​​e LifecycleSave 文件选项解决了问题。文件->保存->属性->另存为,然后看保存类型,默认是Acrobat 7.0.5动态PDF表单文件,我们改为使用7.0.5静态PDF表单文件(其实任何静态的都会工作)。静态保存的文件不存在此水印消失问题。感谢马克指出了正确的方向。

We solved problem by change Adobe LifecycleSave file option. File->Save->properties->Save as, then look at Save as type, default is Acrobat 7.0.5 Dynamic PDF Form File, we changed to use 7.0.5 Static PDF Form File (actually any static one will work). File saved in static one do not have this watermark disappear problem. Thanks Mark for pointing to the right direction.

宣告ˉ结束 2024-10-28 19:54:44

您使用的是 underContent 而不是 overContent。不要那样做。它让你受制于一些人坚持首先绘制的大的、白色填充的矩形。它是不太好的 PostScript 解释器遗留下来的,并且多年来一直没有必要。


好的,查看您的 PDF 后,我发现问题在于这是一个基于 XFA 的表单(来自 LiveCycle Designer)。 Acrobat 可以(而且经常)根据文件包含的 XFA(一种 xml)重建整个文件。这就是您的更改丢失的方式。当 Acrobat 从 XFA 重建 PDF 时,所有现有 PDF 信息都会被倾斜,包括水印。

实现此功能的唯一方法是将水印定义为 PDF 中包含的 XFA 文件的一部分。

检测这些表单并不那么困难:

PdfReader reader = new PdfReader(...);
AcroFields acFields = reader.getAcroFields();
XfaForm xfaForm = acFields.getXfaForm();
if (xfaForm != null && xfaForm.isXfaPresent()) {
  // Ohs nose.
  throw new ItsATrapException("We can't repel XML of that magnitude!");
}

另一方面,修改它们可能相当具有挑战性,但是 这是规格

一旦您弄清楚需要更改什么,这就是一个简单的 XML 操作问题...但是“弄清楚”部分可能会有趣

狩猎好。

You're using the underContent rather than the overContent. Don't do that. It leaves you at the mercy of big, white-filled rectangles that some folks insist on drawing first thing. It's a hold over from less-than-good PostScript interpreters and hasn't been necessary for Many Years.


Okay, having viewed your PDF, I can see the problem is that this is an XFA-based form (from LiveCycle Designer). Acrobat can (and often does) rebuild the entire file based on the XFA (a type of xml) it contains. That's how your changes are lost. When Acrobat rebuilds the PDF from the XFA, all the existing PDF information is pitched, including your watermark.

The only way to get this to work would be to define the watermark as part of the XFA file contained in the PDF.

Detecting these forms isn't all that hard:

PdfReader reader = new PdfReader(...);
AcroFields acFields = reader.getAcroFields();
XfaForm xfaForm = acFields.getXfaForm();
if (xfaForm != null && xfaForm.isXfaPresent()) {
  // Ohs nose.
  throw new ItsATrapException("We can't repel XML of that magnitude!");
}

Modifying them on the other hand could be Quite Challenging, but here's the specs.

Once you've figured out what needs to be changed, it's a simple matter of XML manipulation... but that "figure it out" part could be interesting.

Good hunting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文