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文件生成没有错误。

相关推荐
xrgs_shz2 小时前
MATLAB的数据类型和各类数据类型转化示例
开发语言·数据结构·matlab
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS体育馆管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
Miketutu4 小时前
Spring MVC消息转换器
java·spring
乔冠宇4 小时前
Java手写简单Merkle树
java·区块链·merkle树
LUCIAZZZ5 小时前
简单的SQL语句的快速复习
java·数据库·sql
来恩10035 小时前
C# 类与对象详解
开发语言·c#
komo莫莫da5 小时前
寒假刷题Day19
java·开发语言
ElseWhereR6 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
S-X-S6 小时前
算法总结-数组/字符串
java·数据结构·算法