|
|
@ -2,16 +2,19 @@ package com.ruoyi.common.utils;
|
|
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.io.resource.ClassPathResource;
|
|
|
|
import cn.hutool.core.io.resource.ClassPathResource;
|
|
|
|
import cn.hutool.core.io.resource.Resource;
|
|
|
|
import cn.hutool.core.io.resource.Resource;
|
|
|
|
import com.itextpdf.text.pdf.BaseFont;
|
|
|
|
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 freemarker.template.Configuration;
|
|
|
|
import freemarker.template.Configuration;
|
|
|
|
import freemarker.template.Template;
|
|
|
|
import freemarker.template.Template;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
import org.springframework.util.ResourceUtils;
|
|
|
|
import org.springframework.util.ResourceUtils;
|
|
|
|
import org.xhtmlrenderer.pdf.ITextRenderer;
|
|
|
|
import org.xhtmlrenderer.pdf.ITextRenderer;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.*;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
|
|
|
import java.io.StringWriter;
|
|
|
|
|
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -19,6 +22,7 @@ import java.util.Locale;
|
|
|
|
* @create 2023-05-21 10:38
|
|
|
|
* @create 2023-05-21 10:38
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@Slf4j
|
|
|
|
@Slf4j
|
|
|
|
|
|
|
|
@Component
|
|
|
|
public class PdfUtils {
|
|
|
|
public class PdfUtils {
|
|
|
|
|
|
|
|
|
|
|
|
private final static String TEMPLATE_BASE_PATH = "/template/";//存放文件模板的地址
|
|
|
|
private final static String TEMPLATE_BASE_PATH = "/template/";//存放文件模板的地址
|
|
|
@ -26,23 +30,46 @@ public class PdfUtils {
|
|
|
|
private final static String DEFAULT_FONT = "font/simsun.ttc";//默认字体资源文件([宋体][simsun.ttc])
|
|
|
|
private final static String DEFAULT_FONT = "font/simsun.ttc";//默认字体资源文件([宋体][simsun.ttc])
|
|
|
|
private final static String ENCODING = "UTF-8";//指定编码
|
|
|
|
private final static String ENCODING = "UTF-8";//指定编码
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void createFile(String templateCode, Object data){
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
String templatePath = ResourceUtils.getURL("classpath:").getPath();
|
|
|
|
|
|
|
|
createPDF(templateCode,data,templatePath);
|
|
|
|
|
|
|
|
waterMark(getPath("test.pdf"),templatePath+"photo/watermark.jpg");
|
|
|
|
|
|
|
|
}catch (Exception e){
|
|
|
|
|
|
|
|
log.error("PDF导出异常", e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private String getPath(String fileName){
|
|
|
|
|
|
|
|
return System.getProperty("user.dir") + "/" + fileName;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private FileOutputStream getOutputStream(String fileName) throws IOException {
|
|
|
|
|
|
|
|
String path = getPath(fileName);
|
|
|
|
|
|
|
|
File file = new File(path);
|
|
|
|
|
|
|
|
if (!file.exists()){
|
|
|
|
|
|
|
|
file.createNewFile();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return new FileOutputStream(file);
|
|
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 生成pdf
|
|
|
|
* 生成pdf
|
|
|
|
* @param templateCode 模板
|
|
|
|
* @param templateCode 模板
|
|
|
|
* @param data 传入到freemarker模板里的数据
|
|
|
|
* @param data 传入到freemarker模板里的数据
|
|
|
|
* @param out 生成的pdf文件流
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public static void createPDF(String templateCode, Object data, OutputStream out, String imgName) {
|
|
|
|
public void createPDF(String templateCode, Object data, String templatePath) {
|
|
|
|
|
|
|
|
FileOutputStream fileOutputStream = null;
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
|
|
|
|
fileOutputStream = getOutputStream("test.pdf");
|
|
|
|
// 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
|
|
|
|
// 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
|
|
|
|
Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
|
|
|
|
Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
|
|
|
|
|
|
|
|
|
|
|
|
String path = ResourceUtils.getURL("classpath:").getPath();
|
|
|
|
|
|
|
|
// 指定FreeMarker模板文件的位置
|
|
|
|
// 指定FreeMarker模板文件的位置
|
|
|
|
cfg.setDirectoryForTemplateLoading(new File(path + TEMPLATE_BASE_PATH));
|
|
|
|
cfg.setDirectoryForTemplateLoading(new File(templatePath + TEMPLATE_BASE_PATH));
|
|
|
|
ITextRenderer renderer = new ITextRenderer();
|
|
|
|
ITextRenderer renderer = new ITextRenderer();
|
|
|
|
// 设置 css中 的字体样式(暂时仅支持宋体和黑体)
|
|
|
|
// 设置 css中 的字体样式(暂时仅支持宋体和黑体)
|
|
|
|
String fontPath = path + DEFAULT_FONT;
|
|
|
|
String fontPath = templatePath + DEFAULT_FONT;
|
|
|
|
renderer.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
|
|
|
|
renderer.getFontResolver().addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
|
|
|
|
// 设置模板的编码格式
|
|
|
|
// 设置模板的编码格式
|
|
|
|
cfg.setEncoding(Locale.CHINA, ENCODING);
|
|
|
|
cfg.setEncoding(Locale.CHINA, ENCODING);
|
|
|
@ -56,12 +83,83 @@ public class PdfUtils {
|
|
|
|
// 把html代码传入渲染器中
|
|
|
|
// 把html代码传入渲染器中
|
|
|
|
renderer.setDocumentFromString(html);
|
|
|
|
renderer.setDocumentFromString(html);
|
|
|
|
renderer.layout();
|
|
|
|
renderer.layout();
|
|
|
|
renderer.createPDF(out, false);
|
|
|
|
renderer.createPDF(fileOutputStream, false);
|
|
|
|
renderer.finishPDF();
|
|
|
|
renderer.finishPDF();
|
|
|
|
out.flush();
|
|
|
|
fileOutputStream.flush();
|
|
|
|
out.close();
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
} catch (Exception e) {
|
|
|
|
log.error("PDF导出异常", e);
|
|
|
|
log.error("PDF导出异常", e);
|
|
|
|
|
|
|
|
}finally {
|
|
|
|
|
|
|
|
if (fileOutputStream != null) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
fileOutputStream.flush();
|
|
|
|
|
|
|
|
fileOutputStream.close();
|
|
|
|
|
|
|
|
} catch (final IOException e) {
|
|
|
|
|
|
|
|
log.error("failed to close outputStream!", e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public boolean waterMark(String inputFile, String picFilePath) throws IOException, DocumentException {
|
|
|
|
|
|
|
|
PdfReader reader = null;
|
|
|
|
|
|
|
|
PdfStamper stamper = null;
|
|
|
|
|
|
|
|
FileOutputStream fileOutputStream = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
int picRowNum = 7;
|
|
|
|
|
|
|
|
int picColNum = 4;
|
|
|
|
|
|
|
|
float transDegree = 0.5f;
|
|
|
|
|
|
|
|
reader = new PdfReader(inputFile);
|
|
|
|
|
|
|
|
fileOutputStream = getOutputStream("test1.pdf");
|
|
|
|
|
|
|
|
stamper = new PdfStamper(reader,fileOutputStream);
|
|
|
|
|
|
|
|
// 设置水印支持中文
|
|
|
|
|
|
|
|
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 使用系统字体
|
|
|
|
|
|
|
|
int total = reader.getNumberOfPages() + 1;
|
|
|
|
|
|
|
|
PdfContentByte watermark;
|
|
|
|
|
|
|
|
// 遍历pdf文件的每页以处理
|
|
|
|
|
|
|
|
for (int i = 1; i < total; i++) {
|
|
|
|
|
|
|
|
// 获得PDF最顶层
|
|
|
|
|
|
|
|
watermark = stamper.getUnderContent(i); //在内容上方加水印
|
|
|
|
|
|
|
|
watermark.saveState();
|
|
|
|
|
|
|
|
PdfGState gs = new PdfGState();
|
|
|
|
|
|
|
|
// 设置透明度范围为0到1
|
|
|
|
|
|
|
|
gs.setFillOpacity(transDegree);
|
|
|
|
|
|
|
|
watermark.setGState(gs);
|
|
|
|
|
|
|
|
watermark.beginText();
|
|
|
|
|
|
|
|
watermark.setFontAndSize(base, 15); //字体大小
|
|
|
|
|
|
|
|
watermark.setColorFill(BaseColor.BLACK); //字体颜色
|
|
|
|
|
|
|
|
for (int col = 1; col < picColNum+1; col++) {
|
|
|
|
|
|
|
|
for (int row = 1; row < picRowNum+1; row++) {
|
|
|
|
|
|
|
|
if (picFilePath != null || !"".contentEquals(picFilePath)) {
|
|
|
|
|
|
|
|
// 设置图片水印
|
|
|
|
|
|
|
|
Image image = Image.getInstance(picFilePath);
|
|
|
|
|
|
|
|
image.setAbsolutePosition(100f, 250f);
|
|
|
|
|
|
|
|
image.scaleAbsolute(500, 500); // 自定义大小
|
|
|
|
|
|
|
|
watermark.setGState(gs); // 设置透明度
|
|
|
|
|
|
|
|
watermark.addImage(image); // 添加水印图片
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 添加水印文字
|
|
|
|
|
|
|
|
watermark.endText();
|
|
|
|
|
|
|
|
watermark.setLineWidth(1f);
|
|
|
|
|
|
|
|
watermark.stroke();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
stamper.close();
|
|
|
|
|
|
|
|
reader.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
}finally {
|
|
|
|
|
|
|
|
if (stamper != null){
|
|
|
|
|
|
|
|
stamper.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reader != null){
|
|
|
|
|
|
|
|
reader.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fileOutputStream != null){
|
|
|
|
|
|
|
|
fileOutputStream.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|