我正在使用itext5创建带有不可去除水印的pdf文件,如下所示:
public class TestWatermark {
public static String resourcesPath = "C:\\Users\\java\\Desktop\\TestWaterMark\\";
public static String FILE_NAME = resourcesPath + "test.pdf";
public static void main(String[] args) throws IOException {
System.out.println("########## STARTED ADDING WATERMARK ###########");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] byteArray = Files.readAllBytes(Paths.get(FILE_NAME));
String watermarkText = "confidential";
String fontPath = resourcesPath + "myCustomFont.ttf";
Font arabicFont = FontFactory.getFont(fontPath, BaseFont.IDENTITY_H, 16);
BaseFont baseFont = arabicFont.getBaseFont();
PdfReader reader = new PdfReader(byteArray);
PdfStamper stamper = new PdfStamper(reader, baos);
int numberOfPages = reader.getNumberOfPages();
float height = baseFont.getAscentPoint(watermarkText, 24) + baseFont.getDescentPoint(watermarkText, 24);
for (int i = 1; i <= numberOfPages; i++) {
Rectangle pageSize = reader.getPageSizeWithRotation(i);
PdfContentByte overContent = stamper.getOverContent(i);
PdfPatternPainter bodyPainter = stamper.getOverContent(i).createPattern(pageSize.getWidth(),
pageSize.getHeight());
BaseColor baseColor = new BaseColor(10, 10, 10);
bodyPainter.setColorStroke(baseColor);
bodyPainter.setColorFill(baseColor);
bodyPainter.setLineWidth(0.85f);
bodyPainter.setLineDash(0.2f, 0.2f, 0.2f);
PdfGState state = new PdfGState();
state.setFillOpacity(0.3f);
overContent.saveState();
overContent.setGState(state);
for (float x = 70f; x < pageSize.getWidth(); x += height + 100) {
for (float y = 90; y < pageSize.getHeight(); y += height + 100) {
bodyPainter.beginText();
bodyPainter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_FILL);
bodyPainter.setFontAndSize(baseFont, 13);
bodyPainter.showTextAlignedKerned(Element.ALIGN_MIDDLE, watermarkText, x, y, 45f);
bodyPainter.endText();
overContent.setColorFill(new PatternColor(bodyPainter));
overContent.rectangle(pageSize.getLeft(), pageSize.getBottom(), pageSize.getWidth(),
pageSize.getHeight());
overContent.fill();
}
}
overContent.restoreState();
}
stamper.close();
reader.close();
byteArray = baos.toByteArray();
File outputFile = new File(resourcesPath + "output.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
Files.write(outputFile.toPath(), byteArray);
System.out.println("########## FINISHED ADDING WATERMARK ###########");
} catch (Exception e) {
e.printStackTrace();
}
}
}
上述代码使Adobe Pro编辑功能中的水印不可选且不可移除 但问题是,从 VMware Workspace ONE Boxer 电子邮件中打开此 pdf 文件时,不显示水印!
关于如何解决这个问题有什么建议吗?
更新:以下代码在 Boxer PDF Viewer 中工作正常,水印显示正常,但问题是该水印可由 adobe pro 选择和删除:
public class TestWatermark2 {
public static String resourcesPath = "C:\\Users\\java\\Desktop\\TestWaterMark\\";
public static String FILE_NAME = resourcesPath + "test.pdf";
public static void main(String[] args) throws IOException {
System.out.println("########## STARTED ADDING WATERMARK ###########");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] byteArray = Files.readAllBytes(Paths.get(FILE_NAME));
String watermarkText = "confidential";
String fontPath = resourcesPath + "myCustomFont.ttf";
Font arabicFont = FontFactory.getFont(fontPath, BaseFont.IDENTITY_H, 16);
BaseFont baseFont = arabicFont.getBaseFont();
PdfReader reader = new PdfReader(byteArray);
PdfStamper stamper = new PdfStamper(reader, baos);
Phrase watermarkPhrase = new Phrase(watermarkText, arabicFont);
int numberOfPages = reader.getNumberOfPages();
float height = baseFont.getAscentPoint(watermarkText, 24) + baseFont.getDescentPoint(watermarkText, 24);
for (int i = 1; i <= numberOfPages; i++) {
Rectangle pageSize = reader.getPageSizeWithRotation(i);
PdfContentByte overContent = stamper.getOverContent(i);
PdfGState state = new PdfGState();
state.setFillOpacity(0.3f);
overContent.saveState();
overContent.setGState(state);
for (float x = 70f; x < pageSize.getWidth(); x += height + 100) {
for (float y = 90; y < pageSize.getHeight(); y += height + 100) {
ColumnText.showTextAligned(overContent, Element.ALIGN_CENTER, watermarkPhrase, x, y, 45f,
PdfWriter.RUN_DIRECTION_RTL, ColumnText.DIGITS_AN2EN);
}
}
overContent.restoreState();
}
stamper.close();
reader.close();
byteArray = baos.toByteArray();
File outputFile = new File(resourcesPath + "output.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
Files.write(outputFile.toPath(), byteArray);
System.out.println("########## FINISHED ADDING WATERMARK ###########");
} catch (Exception e) {
e.printStackTrace();
}
}
}
您可以使用 PDF 文件作为水印,而不是在代码中创建它。
此外,请考虑创建一个单独的文件,而不是转换原始文件并重复使用同一文件,然后创建一个新文件,其中的工作表已使用水印更新。
这就是我过去使用它的方式,当然从未遇到过任何问题。您可以阅读我从 github 创建的示例:https://github.com/web20opensource/stamper/blob/master/README.md
我想说与你的代码的区别,主要是pdf水印是单独创建到pdf中,然后用它来标记pdf你想要的pdf水印。
关于资源您可以找到我当时(几年前)从 Max Vogella 使用的教程,这是一个非常透明、清晰、很棒的资源。
我正在使用相同版本的文本(itextpdf-5.4.2.jar),今天可能有重大更新,请在网站上查看最新版本。
我遇到的这个问题不一样但相似,使用画布帮助我实现了。
PdfContentByte canvas = writer.getDirectContext();
//添加内容
canvas.addTemplate(writer.getImportedPage(reader, pageNum), 0,0);
//添加水印
canvas.beginText();canvas.setFontandSize(BaseFont.createFont(),40);canvas.showTextAligned(Element.ALIGN_CENTER, "CONFIDENTIAL", 300, 400, 45);canvas.endText();
}