Пожалуйста, посмотрите пример TransparentWatermark2 . Он добавляет прозрачный текст на каждую нечетную страницу и прозрачное изображение на каждой четной странице существующего документа PDF.
Вот как это делается:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
// text watermark
Font f = new Font(FontFamily.HELVETICA, 30);
Phrase p = new Phrase("My watermark (text)", f);
// image watermark
Image img = Image.getInstance(IMG);
float w = img.getScaledWidth();
float h = img.getScaledHeight();
// transparency
PdfGState gs1 = new PdfGState();
gs1.setFillOpacity(0.5f);
// properties
PdfContentByte over;
Rectangle pagesize;
float x, y;
// loop over every page
for (int i = 1; i <= n; i++) {
pagesize = reader.getPageSizeWithRotation(i);
x = (pagesize.getLeft() + pagesize.getRight()) / 2;
y = (pagesize.getTop() + pagesize.getBottom()) / 2;
over = stamper.getOverContent(i);
over.saveState();
over.setGState(gs1);
if (i % 2 == 1)
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0);
else
over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
over.restoreState();
}
stamper.close();
reader.close();
}
Как вы можете видеть, мы создаем объект Phrase
для текста и объект Image
для изображения. Мы также создаем объект PdfGState
для прозрачности. В нашем случае мы идем на 50% непрозрачность (измените 0.5f
на что-то еще, чтобы экспериментировать).
Как только у нас есть эти объекты, мы перебираем каждую страницу. Мы используем объект PdfReader
, чтобы получить информацию о существующем документе, например размеры каждой страницы. Мы используем объект PdfStamper
, когда хотим отпечатать дополнительный контент в существующем документе, например добавление водяного знака поверх каждой отдельной страницы.
При изменении состояния графики всегда безопасно выполнять a saveState()
, прежде чем вы начнете, и restoreState()
, как только вы закончите. Вы, вероятно, будете работать, если вы этого не сделаете, но поверьте мне: он может сэкономить вам много времени отладки, если вы примете дисциплину для этого, так как вы можете получить действительно странные эффекты, если состояние графики не сбалансировано.
Мы применяем прозрачность с использованием метода setGState()
и в зависимости от того, является ли страница нечетной или четной страницей, мы добавляем текст (используя ColumnText
и координату (x, y)
, рассчитанные так, чтобы текст добавляется посередине каждой страницы) или изображение (используя метод addImage()
и соответствующие параметры для матрицы преобразования).
Как только вы сделали это для каждой страницы документа , вы должны close()
stamper
и reader
.
Предостережение:
Вы заметите, что страницы 3 и 4 находятся в пейзаже, но есть разница между этими двумя страницами, которые не видны невооруженным глазом. Страница 3 - это на самом деле страница, размер которой определяется так, как если бы это была страница в портрете, но она поворачивалась на 90 градусов. Страница 4 - это страница, размер которой определяется таким образом, что ширина> высота.
Это может повлиять на способ добавления водяного знака, но если вы используете getPageSizeWithRotation()
iText будет адаптироваться. Это может быть не то, что вы хотите: возможно, вы хотите, чтобы водяной знак добавлялся по-другому.
Взгляните на TransparentWatermark3 :
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.setRotateContents(false);
// text watermark
Font f = new Font(FontFamily.HELVETICA, 30);
Phrase p = new Phrase("My watermark (text)", f);
// image watermark
Image img = Image.getInstance(IMG);
float w = img.getScaledWidth();
float h = img.getScaledHeight();
// transparency
PdfGState gs1 = new PdfGState();
gs1.setFillOpacity(0.5f);
// properties
PdfContentByte over;
Rectangle pagesize;
float x, y;
// loop over every page
for (int i = 1; i <= n; i++) {
pagesize = reader.getPageSize(i);
x = (pagesize.getLeft() + pagesize.getRight()) / 2;
y = (pagesize.getTop() + pagesize.getBottom()) / 2;
over = stamper.getOverContent(i);
over.saveState();
over.setGState(gs1);
if (i % 2 == 1)
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0);
else
over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
over.restoreState();
}
stamper.close();
reader.close();
}
В этом случай, мы не используем getPageSizeWithRotation()
, а просто getPageSize()
. Мы также сообщаем stamper
not для компенсации существующего вращения страницы: stamper.setRotateContents(false);
Взгляните на разницу в полученных PDF-файлах:
На первом снимке экрана (см. Стр. 3 и 4 результирующего PDF-файла TransparentWatermark2
) страница слева представляет собой страницу с портретом, повернутую на 90 градусов. iText, однако, относится к нему так, как если бы это была страница в ландшафте точно так же, как и страница справа.
[/g4]
Во втором снимке экрана (показ страницы 3 и 4 полученного PDF-файла TransparentWatermark3
), страница слева - это страница с портретом, повернутая на 90 градусов, и мы добавляем водяной знак, как если бы страница была в портрете. В результате водяной знак также поворачивается на 90 градусов. Это не происходит со страницей справа, потому что эта страница имеет поворот на 0 градусов.
[/g5]
Это тонкая разница, но Я думал, что вы хотите знать.
Если вы хотите прочитать этот ответ на французском языке, прочитайте Комментарий créer un filigrane transparent en PDF?
Вы можете отправить push-уведомление с помощью почтальона, отправив на URL:
https://fcm.googleapis.com/fcm/send
Method: POST
, не забудьте добавить в заголовок:
Authorization:key=yourServerKeyFromFirebaseTestEnvironment
Content-Type:application/json
И когда вам нужно отправить в вашей тестовой среде вам нужно создать тестовую среду firebase и использовать ее ключ сервера
Firebase не предоставляет тестовых сред, вы можете создать новое приложение в существующем проекте и использовать ключ API этого приложения для тестирования.