Springboot vue pdf/图片 加水印下载

1:引入 包

<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.27</version>
</dependency>
 
simfang.ttf  文件下载
 https://pan.baidu.com/s/1HP4CHdanRz_Cs_jONX7b-g 提取码: mtwv 
 
2前端代码:

downloadFile(fileUrl, filename) {
if(filename==null||filename==""){
this.$modal.msgError("文件名为空,无法下载")
return
}
if(filename.indexOf(".pdf") !== -1){
//return
}else{
//
let hz = [".png",".jpg",".jpeg",".bmp",".gif"];
let name = "."+filename.split(".")[1];
if(hz.indexOf(name) !== -1){

}else{
this.$modal.msgError("只能导出 图片 或是 pdf 文件")
return
}
}

//网络图片路径    文件名

let queryParams = {"fileUrl":fileUrl,"filename":filename};

this.download('/fileWatermark/download', {
...queryParams
}, filename)
}

3:后端


import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;

@RestController
@RequestMapping("/fileWatermark")
public class FileWatermarkController {

/**
* 下载
* @param response
* @param query 自定义的实体入参
* @throws IOException
*/
@PostMapping("/download")
public void downloadTemplate(HttpServletResponse response,@RequestBody zdyQuery query) throws IOException {
//前端传来的文件名
String filename = query.getFilename();
//获取网络上的pdf/图片 文件流
URL url = new URL(query.getFileUrl()); //网络pdf/图片的URL地址
URLConnection con = url.openConnection();
con.setConnectTimeout(5000); //连接超时时间
InputStream inputStream = con.getInputStream();//将pdf文件转成流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

if(filename!=null&&filename.indexOf(".pdf")!=-1){
// 读取原始 PDF 文件,通过pdf/图片文件的 流 初始化PDDocument
PDDocument document = PDDocument.load(inputStream);
//获取 项目中 resources/tempExcel/simfang.ttf 文件
Resource resource = new ClassPathResource("tempExcel"+System.getProperty("file.separator")+"simfang.ttf");
//通过 simfang.ttf 的文件流初始化 font 这样可以支持中文
//这里需要注意  通过Resource 获取项目下的文件要用  流 初始化PDFont    不要用resource.getFile()
PDFont font = PDType0Font.load(document,resource.getInputStream());
//调用工具类添加水印
FileWatermarkUtil.addPdfWatermark(document,font);
document.save(outputStream);
//设置响应头信息
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream; charset=UTF-8");
StringBuffer contentDisposition = new StringBuffer("attachment; filename=''");
contentDisposition.append(" ").append("''");
response.setHeader("Content-disposition", contentDisposition.toString());
OutputStream out = response.getOutputStream();
outputStream.writeTo(out);
inputStream.close();
out.close();
outputStream.close();
document.close();
}else{
String [] filenames = filename.split("\\.");
String wh = "jpg";
if(filenames!=null&&filenames.length==2){
wh = filenames[1];
}
// 原始图片
BufferedImage originalImage = ImageIO.read(inputStream);
// 副本(水印)图片
BufferedImage watermarkedImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_INT_RGB);
//调用工具类添加水印
FileWatermarkUtil.addImgWatermark(watermarkedImage,originalImage);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream; charset=UTF-8");
StringBuffer contentDisposition = new StringBuffer("attachment; filename=''");
contentDisposition.append(" ").append("''");
response.setHeader("Content-disposition", contentDisposition.toString());
OutputStream out = response.getOutputStream();
ImageIO.write(watermarkedImage, wh, out);
out.close();
}
}
}

工具类:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.pdfbox.util.Matrix;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
* 添加水印工具类
*/
public class FileWatermarkUtil {

/**
* 添加PDF水印
*/
public static void addPdfWatermark(PDDocument document,PDFont font ) throws IOException {
// 遍历PDF文件,在每一页加上水印
for (int i = 0; i < document.getNumberOfPages(); i++) {
//获取每一页
PDPage page = document.getPage(i);
//获取 创建一个内容流
PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);
// 设置字体和字号
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 26);
contentStream.setFont(font, 26);
// 设置透明度
PDExtendedGraphicsState r = new PDExtendedGraphicsState();
r.setNonStrokingAlphaConstant(0.5f);//数值越大水印越黑
r.setAlphaSourceFlag(false);
contentStream.setGraphicsStateParameters(r);

//设置字体颜色
contentStream.setNonStrokingColor(200, 200, 200);

//设置字体居中倾斜 获取高度坐标
PDRectangle mediaBox = page.getMediaBox();

// 添加文本水印
contentStream.beginText();
// 获取PDF页面大小
float pageHeight = mediaBox.getHeight();
float pageWidth = mediaBox.getWidth();
// 根据纸张大小添加水印,30度倾斜 250数值越小 水印个数越多
for (int h = 10; h < pageHeight; h = h + 250) {
for (int w = -10; w < pageWidth; w = w + 250) {
contentStream.setTextMatrix(Matrix.getRotateInstance(0.3, w, h));
contentStream.showText("测试添加水印");
}
}
contentStream.endText();
contentStream.close();
}
}


/**
* 添加 图片 水印
*/
public static void addImgWatermark( BufferedImage watermarkedImage,BufferedImage originalImage) {
// 获取图形 创建画笔
Graphics2D graphics = (Graphics2D) watermarkedImage.getGraphics();
// 绘制图片
graphics.drawImage(originalImage, 0, 0, null);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));

//设置颜色
graphics.setColor(Color.darkGray);
//获取图片的高宽
int height = originalImage.getHeight();
int width = originalImage.getWidth();
String name = "测试添加水印";

double scale = 1.0;
if(width < height){
scale = (double) width / height;
}
int fontSize = (int) Math.ceil((double) (height / 15) * scale);
// 设置字体 画笔字体样式为宋体,加粗,文字大小按比例给
graphics.setFont(new Font("宋体", Font.BOLD, fontSize));

// 水印旋转度
graphics.rotate(Math.toRadians(-25), (double) width / 2, (double) height / 2);

int x = -width * 3;
int y;
// 计算水印文字的宽度
FontMetrics fontMetrics = graphics.getFontMetrics();
int watermarkWidth = fontMetrics.stringWidth(name);
// 水印横向间隔
int positionWidth = (int)(width * 0.25);
// 水印竖向间隔
int positionHeight = (int)(height * 0.35);

while (x < width * 3) {
y = -height * 3;
while (y < height * 3) {
graphics.drawString(name, x, y);
y += fontSize + positionWidth;
}
x += watermarkWidth + positionHeight;
}
graphics.dispose();
}


/**
* 获取字符串占用的宽度
* <br>
*
* @param str 字符串
* @param fontSize 文字大小
* @return 字符串占用的宽度
*/
public static int getStrWidth(String str, int fontSize) {
char[] chars = str.toCharArray();
int fontSize2 = fontSize / 2;

int width = 0;

for (char c : chars) {
int len = String.valueOf(c).getBytes().length;
// 汉字为3,其余1
// 可能还有一些特殊字符占用2等等,统统计为汉字
if (len != 1) {
width += fontSize;
} else {
width += fontSize2;
}
}
return width == 0 ? 1 : width;
}

}
 
效果:
 
 pdf:

 图片 :

 

posted @ 2024-04-19 09:37  雪儿蛇王  阅读(134)  评论(0编辑  收藏  举报