下载PDF添加水印
添加图片水印
话不多说,直接开干:
1.导入需要的jar包
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
itextpdf包为生成pdf的工具包,itext-asian包含了可以了一些字体信息,如果只是添加图片水印可以不导入itext-asian。关于字体,itext除了可以使用itext-asian中的字体,还可以使用ttf字体。
需要注意的是jar包版本之间的兼容,itext在5.0.x版本之前的groupId是com.lowagie,如果用5.0之前版本的itextpdf配合itext-asian,可能导致找不到对应的字体。
2.使用
参考博客:https://www.cnblogs.com/qlqwjy/p/9326468.html
/**
*
* @param bos 输出文件的位置
* @param input
* 原PDF位置
* @throws DocumentException
* @throws IOException
*/
public static void setWatermark(BufferedOutputStream bos, String input)
throws DocumentException, IOException {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, bos);
int total = reader.getNumberOfPages() + 1;
PdfGState gs = new PdfGState();
PdfContentByte content;
for (int i = 1; i < total; i++) {
content = stamper.getOverContent(i);// 在内容上方加水印
gs.setFillOpacity(0.3f);//设置图片透明度
content.setGState(gs);
content.beginText();
//设置图片水印
Image image = Image.getInstance("E:/pdfwatermark/150401103429-7.jpg");
image.setAbsolutePosition(100, 200); // set the first background
// image of the absolute
image.scaleToFit(200, 200);
content.addImage(image);
content.endText();
}
stamper.close();
}
以上是只针对添加图片水印所作的处理
写上测试代码:
public static void main(String[] args) throws DocumentException, IOException {
// 要输出的pdf文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("E:/pdfwatermark/output/abc.pdf")));
// 将pdf文件先加水印然后输出
setWatermark(bos, "E:/pdfwatermark/watermarktest.pdf");
}
运行效果:
实际需求可能还需要添加文字水印,修改setWatermark(BufferedOutputStream bos, String input)方法:
public static void setWatermark(BufferedOutputStream bos, String input)
throws DocumentException, IOException {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, bos);
int total = reader.getNumberOfPages() + 1;
PdfGState gs = new PdfGState();
PdfContentByte content;
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
for (int i = 1; i < total; i++) {
content = stamper.getOverContent(i);// 在内容上方加水印
gs.setFillOpacity(0.3f);
content.beginText();
//添加图片水印
Image image = Image.getInstance("E:/pdfwatermark/150401103429-7.jpg");
image.setAbsolutePosition(100, 200); // set the first background
// image of the absolute
image.scaleToFit(200, 400);
content.setGState(gs);
content.addImage(image);
//添加文字水印
//referenceblog:https://blog.csdn.net/p2073123/article/details/79224833
// content.setColorFill(Color.LIGHT_GRAY);//error
content.setColorFill(BaseColor.RED);//字体颜色
content.setFontAndSize(base, 20);//设置字体样式以及字体大小
content.setTextMatrix(70, 200);
content.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!", 0, 20, 180);//设置文字位置,坐标从左下角算起
content.endText();
}
stamper.close();
}
运行main方法查看效果:
关于字体:
除了可以使用iTextAsian中的字体,还可以使用系统字体文件和或者把字体文件放到项目使用
使用系统字体:
BaseFont.createFont("C:/WINDOWS/Fonts/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
把字体文件放到项目使用:
BaseFont.createFont("/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); //文件可以还可以是ttf文件
相关博客:https://blog.csdn.net/S10011337/article/details/89711008
实现平铺效果
关于文字平铺效果,没有找到可以直接通过设置达到效果的方法,但这部可以通过获取pdf每一页的高度和宽度,再通过循环添加水印的方法达到效果。参考博客:https://blog.csdn.net/qq_33704186/article/details/106442250
下面上代码:
public static void setWatermark(BufferedOutputStream bos, String input)
throws DocumentException, IOException {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, bos);
int total = reader.getNumberOfPages() + 1;
PdfGState gs = new PdfGState();
PdfContentByte content;
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
int interval = 20;
// 获取水印文字的最大高度和宽度
int textH = 0, textW = 0;
JLabel label = new JLabel();
label.setText("公司内部文件,请注意保密!");
FontMetrics metrics = label.getFontMetrics(label.getFont());
textH = metrics.getHeight();
textW = metrics.stringWidth(label.getText());
Rectangle pageSizeWithRotation = null;
for (int i = 1; i < total; i++) {
content = stamper.getOverContent(i);// 在内容上方加水印
gs.setFillOpacity(0.3f);
content.beginText();
//添加图片水印
Image image = Image.getInstance("E:/pdfwatermark/150401103429-7.jpg");
image.setAbsolutePosition(100, 200); // set the first background
// image of the absolute
image.scaleToFit(200, 400);
content.setGState(gs);
content.addImage(image);
//添加文字水印
// content.setColorFill(Color.LIGHT_GRAY);
// content.setColorFill(BaseColor.RED);
// content.setFontAndSize(base, 20);//设置字体样式以及字体大小
// content.setTextMatrix(70, 200);
// content.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!", 200, 250, 0);//设置文字位置,坐标从左下角算起
//获取该页宽度和高度
pageSizeWithRotation = reader.getPageSizeWithRotation(i);
float pageHeight = pageSizeWithRotation.getHeight();
float pageWidth = pageSizeWithRotation.getWidth();
content.setColorFill(BaseColor.RED);
content.setFontAndSize(base, 20);//设置字体样式以及字体大小
// 根据纸张大小多次添加, 水印文字成30度角倾斜
for (int height = interval + textH; height < pageHeight; height = height + textH * 6) {
for (int width = interval + textW; width < pageWidth + textW; width = width + textW * 2) {
content.showTextAligned(Element.ALIGN_LEFT, "公司内部文件,请注意保密!", width - textW, height -(textH+10) * 1, 30);
}
}
content.endText();
}
stamper.close();
}
运行main方法查看效果:
对于最后方法中的一些参数可以提取出来进行进一步优化:
最终代码
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
//参考博客:https://blog.csdn.net/qq_33704186/article/details/106442250
//https://www.cnblogs.com/qlqwjy/p/9326468.html
//https://cloud.tencent.com/developer/article/1472801
//另外一个工具jar https://www.e-iceblue.cn/pdf_java_watermark/java-add-image-watermark-to-pdf.html
//另外一些参考博客 https://www.jianshu.com/p/911d504193cb
// https://blog.csdn.net/weixin_40934096/article/details/100155893
public class WaterMarkUtil {
/**
*
* @param bos 输出文件的位置
* @param input 原PDF位置
* @param waterMarkPicPath 水印图片位置
* @param watermarkWord 水印文字
* @throws DocumentException
* @throws IOException
*/
public static void setWatermark(OutputStream bos, String input, String waterMarkPicPath, String watermarkWord)
throws DocumentException, IOException {
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, bos);
int total = reader.getNumberOfPages() + 1;
PdfGState gs = new PdfGState();
PdfContentByte content;
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
int interval = 20;
// 获取水印文字的最大高度和宽度
/*int textH = 0, textW = 0;
for (int j = 0; j < waterMarkContents.length; j++) {
JLabel label = new JLabel();
label.setText(waterMarkContents[j]);
FontMetrics metrics = label.getFontMetrics(label.getFont());
if (textH < metrics.getHeight()) {
textH = metrics.getHeight();
}
if (textW < metrics.stringWidth(label.getText())) {
textW = metrics.stringWidth(label.getText());
}*/
int textH = 0, textW = 0;
JLabel label = new JLabel();
label.setText(watermarkWord);
FontMetrics metrics = label.getFontMetrics(label.getFont());
textH = metrics.getHeight();
textW = metrics.stringWidth(label.getText());
com.itextpdf.text.Rectangle pageSizeWithRotation = null;
for (int i = 1; i < total; i++) {
content = stamper.getOverContent(i);// 在内容上方加水印
// content = stamper.getUnderContent(i);//在内容下方加水印
gs.setFillOpacity(0.3f);
content.beginText();
//添加图片水印
com.itextpdf.text.Image image = Image.getInstance(waterMarkPicPath);
image.setAbsolutePosition(100, 200); // set the first background
// image of the absolute
image.scaleToFit(200, 400);
content.setGState(gs);//referenceblog:https://blog.csdn.net/p2073123/article/details/79224833
content.addImage(image);
//添加文字水印
// content.setColorFill(Color.LIGHT_GRAY);
// content.setColorFill(BaseColor.RED);
// content.setFontAndSize(base, 20);//设置字体样式以及字体大小
// content.setTextMatrix(70, 200);
// content.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!", 200, 250, 0);//设置文字位置,坐标从左下角算起
//获取纸张宽度和高度
pageSizeWithRotation = reader.getPageSizeWithRotation(i);
float pageHeight = pageSizeWithRotation.getHeight();
float pageWidth = pageSizeWithRotation.getWidth();
content.setColorFill(BaseColor.RED);
content.setFontAndSize(base, 20);//设置字体样式以及字体大小
// 根据纸张大小多次添加, 水印文字成30度角倾斜
for (int height = interval + textH; height < pageHeight; height = height + textH * 6) {
for (int width = interval + textW; width < pageWidth + textW; width = width + textW * 2) {
// 将分段的字段进行输出编写
content.showTextAligned(Element.ALIGN_LEFT, watermarkWord, width - textW, height -(textH+10) * 1, 30);
}
}
content.endText();
}
stamper.close();
}
}
如果项目为web项目,需要实现浏览器下载,可以在controller中调用该方法时可以将传入的OutputStream改为从HttpServletResponse中获取
controller层代码:
@GetMapping("/downloadPdf")
public void downloadPdf(HttpServletRequest request, HttpServletResponse response) throws DocumentException, IOException {
response.addHeader("Content-Disposition", "attachment;filename=" + new String("test.pdf"));
response.setContentType("application/octet-stream;charset=utf-8");
WaterMarkUtil.setWatermark(response.getOutputStream(), "E:/pdfwatermark/watermarktest.pdf","E:/pdfwatermark/150401103429-7.jpg","公司内部文件,请注意保密!");
}
参考博客:https://www.cnblogs.com/qlqwjy/p/9326468.html
https://blog.csdn.net/qq_33704186/article/details/106442250