Java 如何在运行时覆盖两个文档
我需要在运行时添加水印文本,即在创建文档时,我需要添加水印文本。我最初的方法是从文档中获取所有页面,并在这些页面上添加我的文本。Id确实有效,但问题是无论我的水印消息来自何处,它都会隐藏我的页面内容。请参阅我的初始方法代码Java 如何在运行时覆盖两个文档,java,pdfbox,Java,Pdfbox,我需要在运行时添加水印文本,即在创建文档时,我需要添加水印文本。我最初的方法是从文档中获取所有页面,并在这些页面上添加我的文本。Id确实有效,但问题是无论我的水印消息来自何处,它都会隐藏我的页面内容。请参阅我的初始方法代码 List pages = document.getDocumentCatalog().getAllPages(); float fontSize = 70.0f; for (int i = 0; i < pages.size(); i++) {
List pages = document.getDocumentCatalog().getAllPages();
float fontSize = 70.0f;
for (int i = 0; i < pages.size(); i++) {
PDPage page = (PDPage) pages.get(i);
PDRectangle pageSize = page.findMediaBox();
float stringWidth = pdfFont.getStringWidth(text) * fontSize
/ 1000f;
// calculate to center of the page
int rotation = page.findRotation();
boolean rotate = degree > 0;
float pageWidth = rotate ? pageSize.getHeight() : pageSize
.getWidth();
float pageHeight = rotate ? pageSize.getWidth() : pageSize
.getHeight();
double centeredXPosition = rotate ? pageHeight / 2f
: (pageWidth - stringWidth) / 2f;
double centeredYPosition = rotate ? (pageWidth - stringWidth) / 2f
: pageHeight / 2f;
// append the content to the existing stream
PDPageContentStream contentStream = new PDPageContentStream(
document, page, true, true, true);
contentStream.beginText();
// set font and font size
contentStream.setFont(pdfFont, fontSize);
// set text color to red
contentStream.setNonStrokingColor(240, 240, 240);
if (rotate) {
// rotate the text according to the page rotation
contentStream.setTextRotation(degree, x, y);
} else {
contentStream.setTextTranslation(centeredXPosition,
centeredYPosition);
}
contentStream.drawString(text);
contentStream.endText();
contentStream.close();
然后调用这个方法
PDDocument wDoc = createWatermarkText();
//document.addPage(page);
Overlay overlay = new Overlay();
overlay.overlay(wDoc, document);
但是这种方法行不通,我得到的是空白的pdf。非常感谢您的帮助。此答案试图使OP的原始方法发挥作用
原始方法的问题
无论我的水印信息来自何处,它都会隐藏我的页面内容
是由于PDFBoxPDPageContentStream
构造函数将新流添加为最后一个内容流,因此其操作也将最后执行,并最终覆盖之前绘制的内容
因此,为了将新内容推到现有内容之下,我们必须将新流移动到页面内容流中的最前面位置
为了能够做到这一点,我首先更改现有代码:我将水印图形代码括在saveGraphicsState
和restoreGraphicsState
中。这是必要的,以保护原始内容不受标记图形代码状态变化的影响,例如文字颜色变化
...
PDPageContentStream contentStream = new PDPageContentStream(
document, page, true, true, true);
contentStream.saveGraphicsState();
contentStream.beginText();
// set font and font size
contentStream.setFont(pdfFont, fontSize);
// set text color to red
contentStream.setNonStrokingColor(240, 240, 240);
if (rotate) {
// rotate the text according to the page rotation
contentStream.setTextRotation(degree, x, y);
} else {
contentStream.setTextTranslation(centeredXPosition,
centeredYPosition);
}
contentStream.drawString(text);
contentStream.endText();
contentStream.restoreGraphicsState();
contentStream.close();
...
有了此更改,我们只需调用以下方法将水印推送到预先存在的内容下:
void pushUnder(PDDocument document)
{
List<?> pages = document.getDocumentCatalog().getAllPages();
float fontSize = 70.0f;
for (int i = 0; i < pages.size(); i++) {
PDPage page = (PDPage) pages.get(i);
COSBase contents = page.getCOSDictionary().getDictionaryObject(COSName.CONTENTS);
if (contents instanceof COSStreamArray)
{
COSStreamArray contentsArray = (COSStreamArray) contents;
COSArray newArray = new COSArray();
newArray.add(contentsArray.get(0));
newArray.add(contentsArray.get(contentsArray.getStreamCount() - 1));
for (int j = 1; j < contentsArray.getStreamCount() - 1; j++)
{
newArray.add(contentsArray.get(j));
}
COSStreamArray newStreamArray = new COSStreamArray(newArray);
page.getCOSDictionary().setItem(COSName.CONTENTS, newStreamArray);
}
}
}
void pushUnder(PDDocument)
{
列表页面=document.getDocumentCatalog().getAllPages();
浮动字体大小=70.0f;
对于(int i=0;i
()
(如果仔细观察该方法,您会发现我们不会将新流移动到第一个位置,而只移动到第二个位置。我们这样做是因为
new PDPageContentStream(document,page,true,true,true)
constructor调用实际上创建了两个新流,一个在第一个位置,一个在最后一个位置,第一个保存图形状态,最后一个恢复图形状态,然后包含您的操作。在前者之前移动后者将导致在开始时恢复图形状态操作,这将是一个错误。)问题在于,无论我的水印消息来自何处,它都会隐藏我的页面内容-您希望它以何种方式显示?你的页面内容是否应该覆盖水印?或者你想要透明度?我想要我的水印文本在我的页面内容下。好的。我今天一上任就会调查此事。
void pushUnder(PDDocument document)
{
List<?> pages = document.getDocumentCatalog().getAllPages();
float fontSize = 70.0f;
for (int i = 0; i < pages.size(); i++) {
PDPage page = (PDPage) pages.get(i);
COSBase contents = page.getCOSDictionary().getDictionaryObject(COSName.CONTENTS);
if (contents instanceof COSStreamArray)
{
COSStreamArray contentsArray = (COSStreamArray) contents;
COSArray newArray = new COSArray();
newArray.add(contentsArray.get(0));
newArray.add(contentsArray.get(contentsArray.getStreamCount() - 1));
for (int j = 1; j < contentsArray.getStreamCount() - 1; j++)
{
newArray.add(contentsArray.get(j));
}
COSStreamArray newStreamArray = new COSStreamArray(newArray);
page.getCOSDictionary().setItem(COSName.CONTENTS, newStreamArray);
}
}
}