Freemarker和ItextPDF实际应用

1. FreeMarker模板文件路径

确保FreeMarker模板文件位于正确的路径,并通过Spring Boot自动加载。模板文件放在 src/main/resources/templates/ 目录下,FreeMarker会自动处理这些文件。

java 复制代码
@Configuration
public class FreeMarkerConfig {

    @Value("${spring.freemarker.prefix:classpath:/templates/}")
    private String freemarkerTemplatePrefix;

    @Bean
    public Configuration freemarkerConfiguration() {
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
        try {
            configuration.setDirectoryForTemplateLoading(new File(freemarkerTemplatePrefix));
        } catch (IOException e) {
            e.printStackTrace();
        }
        configuration.setDefaultEncoding("UTF-8");
        return configuration;
    }
}

2. 模板文件(template.ftl)

模板文件内容,放在 src/main/resources/templates/ 目录下:

ftl 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>${title}</title>
</head>
<body>
    <h1>${title}</h1>
    <p>${content}</p>
</body>
</html>

3. 图片路径(seal.png)

将章图片 seal.png 放在 src/main/resources/static/images/ 目录下。Spring Boot会自动处理这些资源,你可以通过类加载器获取并加载它。

4. PDF生成逻辑(PDFGenerator.java)

改进后的 PDFGenerator.java,支持动态加载模板和图片,生成带章的PDF文件,并灵活调整章的位置。

java 复制代码
package com.example.demo;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.Image;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

@Service
public class PDFGenerator {

    public void generatePdfWithSeal(String outputPdfPath, String sealImagePath) {
        try {
            // 模板数据
            Map<String, Object> dataModel = new HashMap<>();
            dataModel.put("title", "带章的PDF文件");
            dataModel.put("content", "这是一份动态生成的带章PDF文件。");

            // FreeMarker模板文件路径
            String templateFile = "template.ftl";

            // 创建FreeMarker配置
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
            cfg.setClassForTemplateLoading(PDFGenerator.class, "/templates");  // 设置模板目录
            Template template = cfg.getTemplate(templateFile);

            // 使用FreeMarker处理模板
            StringWriter stringWriter = new StringWriter();
            template.process(dataModel, stringWriter);
            String generatedText = stringWriter.toString();

            // 创建PDF文件
            createPdfWithSeal(outputPdfPath, generatedText, sealImagePath);  // 图片路径

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void createPdfWithSeal(String outputPdfPath, String text, String sealImagePath) throws Exception {
        // 创建一个空的PDF文件
        OutputStream outputStream = new FileOutputStream(outputPdfPath);
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, outputStream);

        document.open();

        // 添加内容
        document.add(new Paragraph(text));

        // 通过类加载器加载章图片(解决WAR包内路径问题)
        InputStream sealInputStream = getClass().getClassLoader().getResourceAsStream(sealImagePath);
        if (sealInputStream != null) {
            Image sealImage = Image.getInstance(sealInputStream);
            // 获取PDF页面的大小,并动态调整章位置
            Rectangle pageSize = writer.getPageSize();
            float x = pageSize.getWidth() - 150;  // 章离右边缘150px
            float y = pageSize.getHeight() - 150;  // 章离下边缘150px
            sealImage.setAbsolutePosition(x, y); 
            sealImage.scaleToFit(100, 100);  // 调整章的大小
            document.add(sealImage);
        } else {
            System.err.println("章文件未找到:" + sealImagePath);
        }

        document.close();
        outputStream.close();
    }
}

5. Spring Boot Controller(PDFController.java)

为了便于测试并下载生成的PDF文件,创建一个REST接口,返回PDF文件流。

java 复制代码
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

@RestController
public class PDFController {

    @Autowired
    private PDFGenerator pdfGenerator;

    @GetMapping("/generate-pdf")
    public ResponseEntity<byte[]> generatePdf() throws IOException {
        String outputPdfPath = "output.pdf";
        String sealImagePath = "images/seal.png";  // 章图片路径

        // 调用PDF生成方法
        pdfGenerator.generatePdfWithSeal(outputPdfPath, sealImagePath);

        File generatedFile = new File(outputPdfPath);
        if (generatedFile.exists()) {
            byte[] fileContent = Files.readAllBytes(generatedFile.toPath());
            // 返回PDF文件作为下载
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"output.pdf\"")
                    .contentType(MediaType.APPLICATION_PDF)
                    .body(fileContent);
        } else {
            return ResponseEntity.status(500).body(null);
        }
    }
}

6. Spring Boot配置(application.properties)

确保配置了FreeMarker模板的正确路径,配置如下:

properties 复制代码
spring.freemarker.prefix=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8

7. 静态资源存放路径

seal.png放在src/main/resources/static/images/目录下,这样Spring Boot会自动处理和提供访问。

8. 目录结构

确保项目目录结构如下:

复制代码
src/
  main/
    java/
      com/
        example/
          demo/
            PDFGenerator.java         // PDF生成逻辑
            PDFController.java        // REST控制器
            DemoApplication.java      // Spring Boot启动类
    resources/
      static/
        images/
          seal.png                  // 章图片
      templates/
        template.ftl                // FreeMarker模板
      application.properties        // Spring Boot配置文件

9. 运行项目

  1. 启动项目:运行Spring Boot应用程序,可以使用命令:

    bash 复制代码
    mvn spring-boot:run
  2. 访问接口:打开浏览器或使用Postman访问:

    复制代码
    http://localhost:8080/generate-pdf

    这会触发PDF生成并返回下载链接。

10. 测试与调试

  1. 如果PDF文件生成成功,它会自动作为附件下载。
  2. 如果出现问题,检查控制台日志,确保:
    • 图片路径正确。
    • 模板路径正确。
    • PDF文件生成没有错误。

相关推荐
Dovis(誓平步青云)9 分钟前
基于面向对象设计的C++日期推算引擎:精准高效的时间运算实现与运算重载工程化实践
开发语言·c++·经验分享·笔记
Java&Develop19 分钟前
springboot + mysql8降低版本到 mysql5.7
java·spring boot·后端
sg_knight21 分钟前
从单体架构到微服务:架构演进之路
java·spring boot·spring·spring cloud·微服务·云原生·架构
夜晚中的人海22 分钟前
【C语言】初阶数据结构相关习题(二)
c语言·开发语言·数据结构
武昌库里写JAVA35 分钟前
MacOS Python3安装
java·开发语言·spring boot·学习·课程设计
Dxy123931021638 分钟前
python如何设置excel单元格边框样式
开发语言·python·excel
eternal__day43 分钟前
Spring Cloud:构建云原生微服务架构的最佳工具和实践
java·spring cloud·微服务·云原生·架构
cdut_suye43 分钟前
【Linux系统】从 C 语言文件操作到系统调用的核心原理
java·linux·数据结构·c++·人工智能·机器学习·云计算
forestsea1 小时前
Maven 插件参数注入与Mojo开发详解
java·maven·mojo
chaodaibing1 小时前
Python解析Excel入库如何做到行的拆分
开发语言·python·excel