基于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 失败");
        }
    }

}
相关推荐
safestar20121 天前
ES批量写入性能调优:BulkProcessor 参数详解与实战案例
java·大数据·运维·jenkins
还在忙碌的吴小二1 天前
Harness 最佳实践:Java Spring Boot 项目落地 OpenSpec + Claude Code
java·开发语言·spring boot·后端·spring
风吹迎面入袖凉1 天前
【Redis】Redis的五种核心数据类型详解
java·redis
liliangcsdn1 天前
mstsc不在“C:\Windows\System32“下在C:\windows\WinSxS\anmd64xxx“问题分析
开发语言·windows
夕除1 天前
javaweb--02
java·tomcat
小陈工1 天前
2026年4月7日技术资讯洞察:下一代数据库融合、AI基础设施竞赛与异步编程实战
开发语言·前端·数据库·人工智能·python
ailvyuanj1 天前
2026年Java AI开发实战:Spring AI完全指南
java
KAU的云实验台1 天前
【算法精解】AIR期刊算法IAGWO:引入速度概念与逆多元二次权重,可应对高维/工程问题(附Matlab源码)
开发语言·算法·matlab
会编程的土豆1 天前
【数据结构与算法】再次全面了解LCS底层
开发语言·数据结构·c++·算法
张np1 天前
java进阶-Dubbo
java·dubbo