基于FreeMarker模板引擎生成Word并导出PDF

基于FreeMarker模板引擎生成Word并导出PDF

1.导入相关maven

xml 复制代码
     <!-- FreeMarker模板引擎 -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <dependency>
            <groupId>aspose</groupId>
            <artifactId>aspose-words</artifactId>
            <version>19.5</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>html2pdf</artifactId>
            <version>4.0.5</version>
        </dependency>

2.FreeMarker渲染数据导出word

java 复制代码
/**
 * Word文档生成工具类
 */
public class WordDocumentGenerator {

    /**
     * 使用FreeMarker生成Word文档
     */
    public static byte[] generateWordDocumentAsBytes(String templatePath, Map<String, Object> root)
            throws IOException, TemplateException {

        // 创建FreeMarker配置
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
        cfg.setDefaultEncoding("UTF-8");

        // 设置模板加载路径
        ClassPathResource resource = new ClassPathResource(templatePath);
        File templateFile = resource.getFile();
        String templateDir = templateFile.getParent();
        String templateName = templateFile.getName();

        cfg.setDirectoryForTemplateLoading(new File(templateDir));

        // 加载模板
        Template template = cfg.getTemplate(templateName, "UTF-8");

        // 使用ByteArrayOutputStream获取字节流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Writer out = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
        template.process(root, out);
        out.close();

        return outputStream.toByteArray();
    }

    public static InputStream generateWordDocumentAsStream(String templatePath, Map<String, Object> root)
            throws IOException, TemplateException {

        byte[] bytes = generateWordDocumentAsBytes(templatePath, root);
        return new ByteArrayInputStream(bytes);
    }

    /**
     * 使用FreeMarker生成Word文档并返回Base64编码的字符串
     */
    public static String generateWordDocumentAsBase64(String templatePath, Map<String, Object> root)
            throws IOException, TemplateException {

        byte[] bytes = generateWordDocumentAsBytes(templatePath, root);
        return Base64.getEncoder().encodeToString(bytes);
    }


    /**
     * 使用FreeMarker生成Word文档并保存到指定路径
     */
    public static void generateWordDocument(String templatePath, String outputPath, Map<String, Object> root)
            throws IOException, TemplateException {

        // 创建FreeMarker配置
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
        cfg.setDefaultEncoding("UTF-8");

        // 设置模板加载路径
        File templateFile = new File(templatePath);
        String templateDir = templateFile.getParent();
        String templateName = templateFile.getName();

        cfg.setDirectoryForTemplateLoading(new File(templateDir));

        // 加载模板
        Template template = cfg.getTemplate(templateName, "UTF-8");

        // 创建输出目录(如果不存在)
        File outputFile = new File(outputPath);
        outputFile.getParentFile().mkdirs();

        // 写入文件
        try (Writer fileWriter = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(outputFile), "UTF-8"))) {
            template.process(root, fileWriter);
        }
    }

3.导出PDF

说明:因为FreeMarker导出的word文档,本质还是xml文件,所以这里要用到aspose工具,支持xml文件 转化为pdf.

1.安装许可证,不然会出现导出会有水印。

license.xml

xml 复制代码
<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>

AsposeWordToPDFGenerator.java

java 复制代码
public class AsposeWordToPDFGenerator {

    public static boolean getLicense() {
        boolean result = false;
        try {
            // license.xml应放在..\WebRoot\WEB-INF\classes路径下
            InputStream is = WordDocumentGenerator.class.getClassLoader().getResourceAsStream("license.xml");
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
     WordDocumentGenerator     *
     * @param inputStream
     * @param outputStream
     * @param saveTo       SaveFormat {@link SaveFormat }
     */
    public static void conversion(InputStream inputStream, OutputStream outputStream, int saveTo) {
        // 验证License 若不验证则转化出的pdf文档会有水印产生
        if (!getLicense()) {
            return;
        }
        try {
            // Address是将要被转化的word文档
            Document document = new Document(inputStream);

            // 设置字体文件夹路径(根据实际字体存放位置修改)
            String fontPath = AsposeWordToPDFGenerator.class.getClassLoader().getResource("Fonts").getPath();
            FontSettings fontSettings = new FontSettings();
            fontSettings.setFontsFolder(fontPath,true);
            document.setFontSettings(fontSettings);
            for (Section section : document.getSections()) {
                PageSetup pageSetup = section.getPageSetup();
                pageSetup.setTopMargin(20);   // 上边距
                pageSetup.setPaperSize(PaperSize.A4);
                TableCollection tables = section.getBody().getTables();
                for (Table table : tables) {
                    table.setAllowAutoFit(false);
                    RowCollection rows = table.getRows();
                    for (Row row : rows) {
                        CellCollection cells = row.getCells();
                        for (Cell cell : cells) {
                            CellFormat cellFormat = cell.getCellFormat();
                            cellFormat.setFitText(false);
                            cellFormat.setWrapText(true);
                        }
                    }
                }
            }
            // 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            document.save(outputStream, saveTo);
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("word转pdf失败");
        }
    }
    /**
     * Word 转 PDF 并返回 base64 编码
     * @param inputStream Word 文档输入流
     * @return PDF 文件的 base64 编码字符串,转换失败返回 null
     */
    public static String convertToBase64(InputStream inputStream) {
        if (!getLicense()) {
            return null;
        }
        try (java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream()) {
            Document document = new Document(inputStream);
            // 设置字体路径(使用类路径)
            String fontPath = AsposeWordToPDFGenerator.class.getClassLoader().getResource("Fonts").getPath();
            FontSettings fontSettings = new FontSettings();
            fontSettings.setFontsFolder(fontPath, true);
            document.setFontSettings(fontSettings);

            for (Section section : document.getSections()) {
                PageSetup pageSetup = section.getPageSetup();
                pageSetup.setTopMargin(20);
                pageSetup.setPaperSize(PaperSize.A4);
                TableCollection tables = section.getBody().getTables();
                for (Table table : tables) {
                    table.setAllowAutoFit(false);
                    RowCollection rows = table.getRows();
                    for (Row row : rows) {
                        CellCollection cells = row.getCells();
                        for (Cell cell : cells) {
                            CellFormat cellFormat = cell.getCellFormat();
                            cellFormat.setFitText(false);
                            cellFormat.setWrapText(true);
                        }
                    }
                }
            }
            document.save(outputStream, SaveFormat.PDF);
            return Base64.getEncoder().encodeToString(outputStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("word 转 pdf 失败");
        }
    }

}
相关推荐
蛋蛋的就会顺顺的5 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
需要8266 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡6 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
死磕音视频6 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
伯恩bourne8 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
silvamux_8 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
省钱兄--zs9 小时前
深圳24小时自助健身房软硬件解决方案实战指南与开发流程详解
java·数据仓库·spring boot·小程序·架构
顽疲9 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
Wang's Blog9 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
用户21296835261689 小时前
开源了一个 Java 多智能体 LLM 框架 Baton:一个依赖,把 Agent 循环、工具调用、记忆、编排全配齐
java·llm