Spring Boot Freemark 动态导出下载Word文档,Jar包运行可运行

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
    @GetMapping("/doc")
    public void doc(HttpServletResponse response) {
        Map<String, Object> dataMap = new HashMap<>();
        ///姓名
        dataMap.put("name", "zhangsan");
        String result = "";
        String fileName = System.currentTimeMillis() + (int) (Math.random() * 90000 + 10000) + ".doc";
        response.setHeader("content-Type", "application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        // 写入输出流
        ServletOutputStream outputStream = null;
        try {
            // 获取渲染数据
            result = FreeMarkUtils.freemarkerRender(dataMap, "test.ftl");
            // 设置文件名
            outputStream = response.getOutputStream();
            outputStream.write(result.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

test.ftl 放入 resource/templates文件夹中 


import com.itextpdf.text.*;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.ui.freemarker.SpringTemplateLoader;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

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

/**
 * @Description: pdf 导出工具类
 * @Author: LiSaiHang
 * @Date: 2022/1/7 11:30 上午
 */
@Component
@Slf4j
public class FreeMarkUtils {
    private FreeMarkUtils() {
    }

    private volatile static Configuration configuration;

    static {
        if (configuration == null) {
            synchronized (FreeMarkUtils.class) {
                if (configuration == null) {
                    configuration = new Configuration(Configuration.VERSION_2_3_28);
                }
            }
        }
    }

    /**
     * freemarker 引擎渲染 html
     *
     * @param dataMap  传入 html 模板的 Map 数据
     * @param fileName 模板文件名称
     *                 eg: "templates/template.ftl"
     * @return
     */
    public static String freemarkerRender(Map<String, Object> dataMap, String fileName) {
        configuration.setDefaultEncoding("UTF-8");
        configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        try {
            // TODO Jar包运行时,是无法读取classpath下资源文件,可以通过 SpringTemplateLoader 读取资源文件目录
            final SpringTemplateLoader templateLoader = new SpringTemplateLoader(new DefaultResourceLoader(), "classpath:templates");
            configuration.setTemplateLoader(templateLoader);
            configuration.setLogTemplateExceptions(false);
            configuration.setWrapUncheckedExceptions(true);
            Template template = configuration.getTemplate(fileName);
            log.info("填充模板动态数据");
            return FreeMarkerTemplateUtils.processTemplateIntoString(template, dataMap);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 使用 iText 生成 PDF 文档
     *
     * @param htmlTmpStr html 模板文件字符串
     * @param fontFile   所需字体文件(相对路径+文件名)
     */
    public static byte[] createHtml2Pdf(String htmlTmpStr, String fontFile) {
        log.info("根据模板生成PDF文件");
        ByteArrayOutputStream outputStream = null;
        byte[] result = null;
        // 生成 字体临时文件
        // TODO jar包运行后,是无法直接读取 classpath 下的资源文件,需要通过文件流读取,生成临时文件
        final String tempFont = "simsun_temp_" + System.currentTimeMillis() + ".ttc";
        final File tempFile = getTempFile(fontFile, tempFont);
        // TODO jar包运行后,是无法直接读取 classpath 下的资源文件,需要通过文件流读取,生成临时文件
        try {
            outputStream = new ByteArrayOutputStream();
            ITextRenderer renderer = new ITextRenderer();
            renderer.setDocumentFromString(htmlTmpStr);
            ITextFontResolver fontResolver = renderer.getFontResolver();
            // 解决中文支持问题,需要所需字体(ttc)文件
            fontResolver.addFont(tempFile.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            renderer.layout();
            renderer.createPDF(outputStream);
            // 对Html2Pdf 的文件插入水印图片
            final String fileName = System.currentTimeMillis() + (int) (Math.random() * 90000 + 10000) + ".pdf";
            addWaterMark(outputStream.toByteArray(), fileName);
            final ByteArrayOutputStream fileOutputStream = getFileOutputStream(new File(fileName));
            result = fileOutputStream.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
                if (tempFile.exists()) {
                    tempFile.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 文件转字节输出流
     *
     * @param outFile 文件
     * @return
     */
    public static ByteArrayOutputStream getFileOutputStream(File outFile) {
        // 获取生成临时文件的输出流
        InputStream input = null;
        ByteArrayOutputStream bytestream = null;
        try {
            input = new FileInputStream(outFile);
            bytestream = new ByteArrayOutputStream();
            int ch;
            while ((ch = input.read()) != -1) {
                bytestream.write(ch);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                bytestream.close();
                log.info("删除临时文件");
                if (outFile.exists()) {
                    outFile.delete();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bytestream;
    }

    /**
     * 获取资源文件的临时文件
     * 资源文件打jar包后,不能直接获取,需要通过流获取生成临时文件
     *
     * @param fileName 文件路径 temp/temp.ftl
     * @return
     */
    public static File getTempFile(String fileName, String tempFont) {
        final File tempFile = new File(tempFont);
        InputStream fontTempStream = null;
        try {
            fontTempStream = FreeMarkUtils.class.getClassLoader().getResourceAsStream(fileName);
            FileUtils.copyInputStreamToFile(fontTempStream, tempFile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fontTempStream != null) {
                    fontTempStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return tempFile;
    }


    /**
     * 插入图片水印
     * @param srcByte 已生成PDF的字节数组(流转字节)
     * @param destFile 生成有水印的临时文件 temp.pdf
     * @return
     */
    public static FileOutputStream addWaterMark(byte[] srcByte, String destFile) {
        // 待加水印的文件
        PdfReader reader = null;
        // 加完水印的文件
        PdfStamper stamper = null;
        FileOutputStream fileOutputStream = null;
        try {
            reader = new PdfReader(srcByte);
            fileOutputStream = new FileOutputStream(destFile);
            stamper = new PdfStamper(reader, fileOutputStream);
            int total = reader.getNumberOfPages() + 1;
            PdfContentByte content;
            // 设置字体
            //BaseFont font = BaseFont.createFont();
            // 循环对每页插入水印
            for (int i = 1; i < total; i++) {
                final PdfGState gs = new PdfGState();
                // 水印的起始
                content = stamper.getUnderContent(i);
                // 开始
                content.beginText();
                // 设置颜色 默认为蓝色
                //content.setColorFill(BaseColor.BLUE);
                // content.setColorFill(Color.GRAY);
                // 设置字体及字号
                //content.setFontAndSize(font, 38);
                // 设置起始位置
                // content.setTextMatrix(400, 880);
                //content.setTextMatrix(textWidth, textHeight);
                // 开始写入水印
                //content.showTextAligned(Element.ALIGN_LEFT, text, textWidth, textHeight, 45);

                // 设置水印透明度
                // 设置笔触字体不透明度为0.4f
                gs.setStrokeOpacity(0f);
                Image image = null;
                image = Image.getInstance("https://dpxdata.oss-cn-beijing.aliyuncs.com/upload/kbt/null_1660715685801.png");
                // 设置坐标 绝对位置 X Y
                image.setAbsolutePosition(472, 785);
                // 设置旋转弧度
                image.setRotation(0);// 旋转 弧度
                // 设置旋转角度
                image.setRotationDegrees(0);// 旋转 角度
                // 设置等比缩放
                image.scalePercent(4);// 依照比例缩放
                // image.scaleAbsolute(200,100);//自定义大小
                // 设置透明度
                content.setGState(gs);
                // 添加水印图片
                content.addImage(image);
                // 设置透明度
                content.setGState(gs);
                //结束设置
                content.endText();
                content.stroke();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally {
            try {
                stamper.close();
                fileOutputStream.close();
                reader.close();
            } catch (DocumentException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileOutputStream;
    }
}

创建模板文件-test.ftl 

1. 创建word  

2. 另存为 Xml文件

 3. 修改拓展名重命名 ftl

编辑变量,根据自己的业务需求创建动态变量,变量语法可参考Freemark 语法

下载后的word

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值