java - 如何使用iText7 pdfHtml向每个页面添加透明水印文本

标签 java itext itext7

目前,我正在尝试使用 iText7 pdfHtml 添加出现在 pdf 每页背景中的水印,但我无法找到解决方案。例如,我希望文本“ secret ”出现在每个页面的背景中。我尝试像这样用 css 添加它

@page {
    size: Letter;
    margin: .5in .5in .5in .5in;

    @left-middle {
        content: "Confidential";
        /* z-index: 100; */
        font-size: 80pt;
        font-weight: bold;
        opacity: .2;
        text-align: center;
        text-transform: uppercase;
        transform: translateX(350px) rotate(-54.7deg);
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        overflow: auto;
        z-index: 0;
    }
}

这几乎解决了我的问题,但是文本不透明并且掩盖了后面的文本。它也不会旋转,但这不是必要的要求。

欢迎涉及 Java、CSS 或 Html 某种组合的解决方案。

这是我的 Java 代码的示例:

        FileInputStream htmlStream = null;
        FileOutputStream pdfStream = null;

        try {
            ConverterProperties converterProperties = new ConverterProperties().setBaseUri(path);
            converterProperties.setMediaDeviceDescription(new MediaDeviceDescription(MediaType.PRINT));
            htmlStream = new FileInputStream(inputPath);
            pdfStream = new FileOutputStream(outputPath);
            HtmlConverter.convertToPdf(htmlStream, pdfStream, converterProperties);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (htmlStream != null) {
                htmlStream.close();
            }
            if (pdfStream != null) {
                pdfStream.close();
            }
        }

编辑

要重现的示例 html:

<!DOCTYPE html>
<html>
<link id="watermark_link" href="watermark.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <h1>My First Heading</h1>
    <p>My first paragraph.</p>
</body>

</html>

编辑2

尝试了 @BenIngle 的答案后,这里是我的 Java 代码,让它与 pdfHtml 一起工作:

    private static void generatePDFFromHTML(String inputPath, String outputPath, String baseUrl) throws IOException {
        FileInputStream htmlStream = null;
        FileOutputStream pdfStream = null;

        try {
            ConverterProperties converterProperties = new ConverterProperties().setBaseUri(baseUrl);
            converterProperties.setMediaDeviceDescription(new MediaDeviceDescription(MediaType.PRINT));
            htmlStream = new FileInputStream(inputPath);
            pdfStream = new FileOutputStream(outputPath);
            PdfWriter writer = new PdfWriter(pdfStream);
            PdfDocument pdfDocument = new PdfDocument(writer);
            Watermark watermark = new Watermark("Confidential");
            pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE,watermark);
            HtmlConverter.convertToPdf(htmlStream, pdfDocument, converterProperties);
            pdfDocument.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (htmlStream != null) {
                htmlStream.close();
            }
            if (pdfStream != null) {
                pdfStream.close();
            }
        }

    }

    protected static class Watermark implements IEventHandler {

        String watermarkText;

        public Watermark(String watermarkText) {
            this.watermarkText = watermarkText;
        }

        @Override
        public void handleEvent(Event event) {
            //Retrieve document and
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            Rectangle pageSize = page.getPageSize();
            PdfCanvas pdfCanvas = new PdfCanvas(page.getLastContentStream(), page.getResources(), pdf);
            Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
            PdfExtGState gstate = new PdfExtGState();
            gstate.setFillOpacity(.2f);
            pdfCanvas.setExtGState(gstate);

            double rotationDeg = -54.7d;
            double rotationRad = Math.toRadians(rotationDeg);
            Paragraph watermarkParagraph = new Paragraph(watermarkText)
                    .setFontSize(80f)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE)
                    .setRotationAngle(rotationRad)
                    .setFixedPosition(100, page.getPageSize().getHeight(), page.getPageSize().getWidth());
            canvas.add(watermarkParagraph);
            canvas.close();

        }

    }

我希望这可以帮助其他尝试开始使用 iText pdfHtml 的人!

最佳答案

这是“在每个页面的背景中”添加文本的解决方案。这将在现有内容后面添加文本,这样它就不会覆盖它。请注意,这不会增加透明度。需要通过外部图形状态添加透明度。

try (PdfDocument doc = new PdfDocument(new PdfReader(in.toFile()), new PdfWriter(out.toFile()))) {
    PdfFont helvetica = PdfFontFactory.createFont();
    for (int pageNum = 1; pageNum <= doc.getNumberOfPages(); pageNum++) {
        PdfPage page = doc.getPage(pageNum);
        // important - add a new content stream in the beginning, to render behind existing text
        PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), doc);

        // option 1 - manual placement
        canvas.saveState();
        canvas.beginText();
        canvas.setFillColor(ColorConstants.GRAY);
        canvas.setFontAndSize(helvetica, 80f);
        canvas.moveText(0f, page.getPageSize().getHeight() - 80f);
        canvas.showText("Confidential1");
        canvas.endText();
        canvas.restoreState();

        // option 2 - let iText place it
        try (Canvas canvas1 = new Canvas(canvas, doc, page.getPageSize())) {
            Paragraph watermark = new Paragraph("Confidential2")
                    .setFontColor(ColorConstants.GRAY)
                    .setFont(helvetica)
                    .setFontSize(80f)
                    .setHorizontalAlignment(HorizontalAlignment.LEFT)
                    .setVerticalAlignment(VerticalAlignment.BOTTOM)
                    .setFixedPosition(0f, page.getPageSize().getHeight() - 100f, page.getPageSize().getWidth());
            canvas1.add(watermark);
        }

        // option 3 - set opacity and place on top of existing content, plus rotation
        PdfExtGState gstate = new PdfExtGState();
        gstate.setFillOpacity(.2f);
        canvas = new PdfCanvas(page);
        canvas.saveState();
        canvas.setExtGState(gstate);
        try (Canvas canvas2 = new Canvas(canvas, doc, page.getPageSize())) {
            double rotationDeg = -54.7d;
            double rotationRad = Math.toRadians(rotationDeg);
            Paragraph watermark = new Paragraph("Confidential3")
                    .setFont(helvetica)
                    .setFontSize(80f)
                    .setTextAlignment(TextAlignment.CENTER)
                    .setVerticalAlignment(VerticalAlignment.MIDDLE)
                    .setRotationAngle(rotationRad)
                    .setFixedPosition(100, page.getPageSize().getHeight(), page.getPageSize().getWidth());
            canvas2.add(watermark);
        }
        canvas.restoreState();
    }
}

编辑

添加了应用透明度和旋转的第三个选项。

关于java - 如何使用iText7 pdfHtml向每个页面添加透明水印文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55363450/

相关文章:

java - 在另一个 Activity 中使用 RecyclerView 适配器的 ArrayList

java.lang.IncompleteClassChangeError : the number of constructors

java - 从 pdf 中提取嵌入对象

java - 如何合并多个pdf

java - 奇怪的 IText 7 行为 - 错误

asp.net-core - itext7将html转换为pdf(asp.net core 2.1)得到错误 "Cannot access a closed stream"

c# - 调用 PdfFontFactory.CreateFont 时出错,System.NotSupportedException : The invoked member is not supported in a dynamic assembly in c# WebApp

java - Maven项目中资源文件的路径是什么?

java - Android 媒体播放器的速度控制

java - 如何在 Java 中的 PDF 内容的句子中插入单词?