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

}
相关推荐
liulilittle12 分钟前
无锁并发容器的设计与实现原理
开发语言·c++·set·map·并发·无锁·lock-free
朋克洛德的码农36 分钟前
Go并发-sync包四剑客:Mutex、RWMutex、WaitGroup、Once-从入门到原理
开发语言·后端·golang
桦说编程1 小时前
盘点并发集合里那些容易误判的行为
java·后端·性能优化
淼澄研学2 小时前
Kimi API黑产倒卖技术解析与Python合规接入指南
开发语言·网络·python
冻柠檬飞冰走茶2 小时前
PTA基础编程题目集 7-35有理数均值(C++语言实现)
开发语言·数据结构·c++·算法·均值算法
wangchen_02 小时前
C++正则表达式
开发语言·c++·正则表达式
何以解忧,唯有..2 小时前
Python 元组(tuple)详解:使用、遍历与排序
开发语言·python
KANGBboy2 小时前
Python eval安全隐患
开发语言·python
IT爱学堂2 小时前
java版数据结构和算法+AI算法和技能学习指南
java·开发语言
evans在进步3 小时前
LeetCode 394:字符串解码——Java 单栈模拟与嵌套解析详解
java·python·leetcode