1,读取pdf文件,读取自己需要的页数
try (PDDocument document = Loader.loadPDF(new RandomAccessReadBuffer(inputStream))) {
//pageList为需要的pdf页码
if (!CollectionUtils.isEmpty(pageList)) {
PDDocument destinationDocument = new PDDocument();
// 抽取传入的页
for (Integer i : pageList) {
//大于pdf页数的无效配置
if (i > document.getNumberOfPages()) {
continue;
}
PDPage page = document.getPage(i - 1);
destinationDocument.addPage(page);
}
//**添加水印,必须先添加到新的文档对象中再进行水印添加,不能直接添加page对象,字体不会复制
//添加水印方法
extracted(destinationDocument, vo);
// 保存修改后的 PDF 文件
destinationDocument.save(new File(outFilePath));
destinationDocument.close();
}
} catch (IOException e) {
logger.error("水印添加失败:{}", e.getMessage());
}
1.1 上面的代码会有pdf最后一页没有水印的问题(不知道原因)
解决方案是在原pdf上操作删除不需要的页码
//提取需要的页数
if (!CollectionUtils.isEmpty(pageList)) {
for (int i = document.getNumberOfPages()-1; i >=0; i--) {
if (!pageList.contains(i+1)) {
//删除不需要的页
document.removePage(i);
}
}
}
2,读取本地字体
//读取本地字体
InputStream inputStream = new Object() {
public InputStream getPath() {
return Objects.requireNonNull(this.getClass().
getResourceAsStream("/font/字体.ttf"));
}
}.getPath();
PDType0Font font = PDType0Font.load(document, inputStream);
读取resource文件夹下的字体。此工具类是静态方法需要这样读取,如果是注入方式可以换其他方式
3,pdf添加水印
此处代码实现水印3*3三等份居中显示,根据自己需求改动x,y坐标。
// 遍历 PDF 中的所有页面
for (int i = 0; i < document.getNumberOfPages(); i++) {
PDPage page = document.getPage(i);
// 获取页面的宽和高
float width = page.getMediaBox().getWidth();
float height = page.getMediaBox().getHeight();
PDPageContentStream contentStream = new PDPageContentStream(document, page,
PDPageContentStream.AppendMode.APPEND, true, true);
// 设置字体和字号
contentStream.setFont(font, vo.getFontSize());
// 设置颜色
contentStream.setNonStrokingColor(new Color(vo.getRed(), vo.getGreed(), vo.getBlue()));
//透明度
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
extendedGraphicsState.setNonStrokingAlphaConstant(vo.getTransparency());
extendedGraphicsState.setAlphaSourceFlag(true);
extendedGraphicsState.setBlendMode(BlendMode.NORMAL);
contentStream.setGraphicsStateParameters(extendedGraphicsState);
//长宽分成三等分,取中心点
float startY = height / 3 / 2;
float startX = width / 3 / 2;
// 获取水印文字的宽度和高度取中心点
float textWidth = font.getStringWidth(vo.getTxtData()) / 1000 * vo.getFontSize() / 2;
float textHeight = font.getFontDescriptor().getCapHeight() / 1000 * vo.getFontSize() / 2;
//读取水印图片
PDImageXObject pdImageObject = null;
float picWidth = 0;
float picHeight = 0;
if (!ObjectUtils.isEmpty(vo.getImgData())) {
//读取图片
Path tempPath = Files.write(Paths.get(rootSrc), Base64.decode(vo.getImgData()));
pdImageObject = PDImageXObject.createFromFileByExtension(tempPath.toFile(), document);
//图片的宽高
picWidth = pdImageObject.getWidth();
picHeight = pdImageObject.getHeight();
}
//平铺 3*3,不平铺居中显示
float y = startY;
for (int j = 1; j <= 3; j++) {
float x = startX;
if (!vo.getLayFlag() && j != 2) {
y = y + startY * 2;
continue;
}
for (int k = 1; k <= 3; k++) {
if (!vo.getLayFlag() && k != 2) {
x = x + startX * 2;
continue;
}
/*
旋转需要先偏移中心点,后旋转,再偏移回来
*/
Matrix rotateInstance = Matrix.getTranslateInstance(x - textWidth, y - textHeight);
//文字设置
rotateInstance.translate(textWidth, textHeight);
rotateInstance.rotate(Math.toRadians(vo.getRotation()));
rotateInstance.translate(-textWidth, -textHeight);
//图片设置
if (!ObjectUtils.isEmpty(vo.getImgData())) {
Matrix picRotateInstance = Matrix.getTranslateInstance(x - picWidth/2, y - picHeight / 2);
picRotateInstance.translate(picWidth / 2, picHeight / 2);
picRotateInstance.rotate(Math.toRadians(vo.getRotation()));
picRotateInstance.translate(-picWidth / 2, -picHeight / 2);
picRotateInstance.scale(picWidth, picHeight);
contentStream.drawImage(pdImageObject, picRotateInstance);
}
// 添加文本水印
contentStream.beginText();
contentStream.setTextMatrix(rotateInstance);
//水印内容
contentStream.showText(vo.getTxtData());
contentStream.endText();
x = x + startX * 2;
}
y = y + startY * 2;
}
contentStream.close();
}
vo参数定义:
如果前端传入的是16进制编码可以用Color.decode(“#0000FF”)转换成rgb格式。
@Schema(title = "RGB编码:红色")
private int red;
@Schema(title = "RGB编码:绿色")
private int greed;
@Schema(title = "RGB编码:蓝色")
private int blue;
@Schema(title = "文本内容")
private String txtData;
@Schema(title = "字体大小")
private Integer fontSize;
@Schema(title = "内容透明度")
private Float transparency;
@Schema(title = "内容旋转角度")
private Integer rotation;
@Schema(title = "是否平铺")
private Boolean layFlag;
@Schema(title = "图片base64编码")
private String imgData;
4,pdf转jpg模糊
读取pdf时定义dpi为300解决
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(i,300, ImageType.RGB);