浏览代码

file-service 添加一个 pdf 文件生成功能

reghao 1 年之前
父节点
当前提交
e76f36b1ab

+ 13 - 0
file/file-service/pom.xml

@@ -143,6 +143,17 @@
             </exclusions>
         </dependency>
 
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>5.5.11</version>
+        </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itext-asian</artifactId>
+            <version>5.2.0</version>
+        </dependency>
+
         <dependency>
             <groupId>io.springfox</groupId>
             <artifactId>springfox-swagger2</artifactId>
@@ -204,6 +215,8 @@
                     <include>application-${profile.active}.yml</include>
                     <include>mapper/**</include>
                     <include>*.xml</include>
+                    <!-- 前端静态资源 -->
+                    <include>static/**</include>
                 </includes>
             </resource>
         </resources>

+ 74 - 0
file/file-service/src/main/java/cn/reghao/tnb/file/app/service/ReportService.java

@@ -0,0 +1,74 @@
+package cn.reghao.tnb.file.app.service;
+
+import cn.reghao.tnb.file.app.util.pdf.ContentStyle;
+import cn.reghao.tnb.file.app.util.pdf.DateTimeUtil;
+import cn.reghao.tnb.file.app.util.pdf.PDFUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * @author reghao
+ * @date 2024-12-01 11:59:49
+ */
+@Slf4j
+@Service
+public class ReportService {
+    private final String baseDir;
+    private final PDFUtil pdfUtil;
+
+    public ReportService(ServerProperties serverProperties) {
+        this.baseDir = serverProperties.getTomcat().getBasedir().getAbsolutePath();
+        this.pdfUtil = new PDFUtil();
+    }
+
+    public void createCertificate() {
+        //  获取证书背景图片路径
+        String backgroundImage = Objects.requireNonNull(PDFUtil.class.getClassLoader().getResource("static/img/bg.png")).getPath();
+        //  获取发放证书的项目Logo
+        String logo = Objects.requireNonNull(PDFUtil.class.getClassLoader().getResource("static/img/logo.png")).getPath();
+        //  生成的pdf的文件位置
+        String reportPath = String.format("%s/%s.pdf", baseDir, System.currentTimeMillis());
+
+        //  准备证书所需要的数据
+        String trueName = "周子轩";
+        Date examTime = new Date();
+        String userInfo = trueName + "同学:";
+        String examName = "2024期末考试";
+
+        //  证书字体样式
+        ContentStyle style1 = new ContentStyle();
+        style1.setFontSize(15);
+        ContentStyle style2 = new ContentStyle();
+        style2.setFontSize(10);
+        //  生成证书内容
+        String content = "您于" + DateTimeUtil.DateToString(examTime) + "在" + examName + "测评中取得优异成绩!";
+        //  创建证书
+        try {
+            String content1 = "特发此证,以资鼓励!";
+            pdfUtil.openDocument(reportPath)
+                    .addImage(backgroundImage, 0, 400)
+                    //.addLogo(logo, 270, 480)
+                    .addContent(userInfo, 85, 630, style1)
+                    .addContent(content1, 125, 495, style2)
+                    .addLogo(logo, 360, 495);
+
+            //  结束截取字符串的索引
+            int end;
+            //  证书内容分行,防止超出证书边缘
+            for (int i = 0, y = 590; i < content.length(); y -= 30) {
+                end = Math.min(i + 30, content.length());
+                pdfUtil.addContent(content.substring(i, end), 125, y, style1);
+                i = end;
+            }
+        } catch (Exception e) {
+            log.error("生成证书错误: " + e);
+        }
+        //  关闭创建pdf的工具
+        pdfUtil.close();
+        log.info("pdf file path -> {}", reportPath);
+    }
+}

+ 26 - 0
file/file-service/src/main/java/cn/reghao/tnb/file/app/util/pdf/ContentStyle.java

@@ -0,0 +1,26 @@
+package cn.reghao.tnb.file.app.util.pdf;
+
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.Element;
+import com.itextpdf.text.Font;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ContentStyle {
+	// windowss下用这个
+	//private String TTFPath = "C:/WINDOWS/Fonts/SIMYOU.TTF";// 字体类型
+	// linux下用这个
+	private String TTFPath = "/usr/share/fonts/dejavu/DejaVuSans.ttf";// 字体类型
+	private float  fontSize = 12;//字体大小
+	private BaseColor baseColor = new BaseColor(0, 0, 0);//默认是黑色
+	private int style = Font.NORMAL;//字体样式
+	private int alignment = Element.ALIGN_LEFT;
+
+	public String getTTFPath() {
+		return TTFPath;
+	}
+}

+ 19 - 0
file/file-service/src/main/java/cn/reghao/tnb/file/app/util/pdf/DateTimeUtil.java

@@ -0,0 +1,19 @@
+package cn.reghao.tnb.file.app.util.pdf;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DateTimeUtil {
+
+	  public static Date getCurrentDate(){
+		  return new Date(System.currentTimeMillis());
+	  }
+
+	  public static String DateToString(Date date) {
+		  	if(date == null){
+		  		return "";
+		  	}
+		  	SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月dd日 HH时mm分");
+		  	return sdf.format(date);
+	 }
+}

+ 143 - 0
file/file-service/src/main/java/cn/reghao/tnb/file/app/util/pdf/PDFUtil.java

@@ -0,0 +1,143 @@
+package cn.reghao.tnb.file.app.util.pdf;
+
+import com.itextpdf.text.*;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.ColumnText;
+import com.itextpdf.text.pdf.PdfContentByte;
+import com.itextpdf.text.pdf.PdfWriter;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+public class PDFUtil {
+
+    private Document document;
+    private PdfWriter writer;
+
+    /**
+     * 开启创建PDF对象
+     *
+     * @param pafPath : 生成pdf的磁盘路径
+     */
+    public PDFUtil openDocument(String pafPath) throws FileNotFoundException, DocumentException {
+        Document document = new Document();
+        writer = PdfWriter.getInstance(document, new FileOutputStream(pafPath));
+        document.open();
+        this.document = document;
+        return this;
+    }
+
+    /**
+     * 添加图片背景
+     *
+     * @param absoluteX :左边距
+     * @param absoluteY :底边距
+     */
+    public PDFUtil addImage(String imagePath, float absoluteX, float absoluteY) throws IOException, DocumentException {
+        Image tImgCover = Image.getInstance(imagePath);
+        tImgCover.setAbsolutePosition(absoluteX, absoluteY);
+        float heigth = tImgCover.getHeight();
+        float width = tImgCover.getWidth();
+        // int percent=getPercent(heigth, width);
+        int percent = getPercent2(heigth, width);
+        // 设置图片居中显示
+        // tImgCover.setAlignment(Image.MIDDLE);
+        tImgCover.scalePercent(percent);// 表示是原来图像的比例;
+        document.add(tImgCover);
+        return this;
+    }
+
+    public PDFUtil addLogo(String imagePath, float absoluteX, float absoluteY) throws IOException, DocumentException {
+        Image tImgCover = Image.getInstance(imagePath);
+        tImgCover.setAbsolutePosition(absoluteX, absoluteY);
+        tImgCover.scalePercent(20);// 表示是原来图像的比例;
+        document.add(tImgCover);
+        return this;
+    }
+
+    /**
+     * @param certificateContent :pdf证书的中文内容
+     * @param x                  :左边距
+     * @param y                  :底边距
+     * @param contentStyle       :中文内容的样式
+     */
+    public PDFUtil addContent(String certificateContent, float x, float y, ContentStyle contentStyle) throws DocumentException, IOException {
+
+        if (contentStyle == null) {
+            contentStyle = new ContentStyle();
+        }
+
+        PdfContentByte canvas = writer.getDirectContent();
+        // windows下用下面的
+//        BaseFont bf = BaseFont.createFont(contentStyle.getTTFPath(),BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+        // linux用这个
+        BaseFont bf = BaseFont.createFont("STSong-Light",
+                "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
+        Font secFont = new Font(bf, contentStyle.getFontSize(), contentStyle.getStyle(), contentStyle.getBaseColor());
+        Phrase certificateContentPhrase = new Phrase(certificateContent, secFont);
+        ColumnText.showTextAligned(canvas, contentStyle.getAlignment(), certificateContentPhrase, x, y, 0);
+        return this;
+    }
+
+    /**
+     * 添加日期内容
+     *
+     * @param x 插入pdf左边距
+     * @param y 插入pdf底边距
+     */
+    public PDFUtil addDateContent(float x, float y, ContentStyle contentStyle) throws DocumentException, IOException {
+
+        if (contentStyle == null) {
+            contentStyle = new ContentStyle();
+        }
+
+        Date currentDate = DateTimeUtil.getCurrentDate();
+        String currentDateString = DateTimeUtil.DateToString(currentDate);
+
+        PdfContentByte canvas = writer.getDirectContent();
+        BaseFont bf = BaseFont.createFont(contentStyle.getTTFPath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+        Font secFont = new Font(bf, contentStyle.getFontSize(), contentStyle.getStyle(), contentStyle.getBaseColor());
+        Phrase certificateDatephrase = new Phrase(currentDateString, secFont);
+        ColumnText.showTextAligned(canvas, contentStyle.getAlignment(), certificateDatephrase, x, y, 0);
+        return this;
+    }
+
+    /**
+     * 释放资源
+     */
+    public void close() {
+        document.close();
+    }
+
+    /**
+     * 第二种解决方案,统一按照宽度压缩
+     * 这样来的效果是,所有图片的宽度是相等的,自我认为给客户的效果是最好的
+     */
+    public int getPercent2(float h, float w) {
+        int p = 0;
+        float p2 = 0.0f;
+        p2 = 595 / w * 100;
+        System.out.println("--" + p2);
+        p = Math.round(p2);
+        return p;
+    }
+
+    /**
+     * 第一种解决方案
+     * 在不改变图片形状的同时,判断,如果h>w,则按h压缩,否则在w>h或w=h的情况下,按宽度压缩
+     */
+
+    public int getPercent(float h, float w) {
+        int p = 0;
+        float p2 = 0.0f;
+        if (h > w) {
+            p2 = 297 / h * 100;
+        } else {
+            p2 = 210 / w * 100;
+        }
+        p = Math.round(p2);
+        return p;
+    }
+}

二进制
file/file-service/src/main/resources/static/img/bg.png


二进制
file/file-service/src/main/resources/static/img/logo.png