利用Freemark模板生成word、pdf文档

前言

这是两三年前刚实习时,项目经理要求我研究一下模板文件动态生成word、pdf,最近在整理笔记时将其翻了出来

操作步骤

引入依赖

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>
复制代码

将word模板文件转换为ftl文件

image

点击另存为.xml格式文件

image

重命名为 信息表.ftl 即可

image

将ftl文件转换为docx文件

代码如下


import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DocUtil {
    private Configuration configuration = null;
    public DocUtil() {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
    }
    /**
     *
     * @param dataMap 入参数据
     * @param ftlPath ftl文件存放路径(不包括文件名)
     * @param ftlName ftl文件名
     * @param outfile 生成的docx文件
     * @throws UnsupportedEncodingException
     */
    public void createDoc(Map<String, Object> dataMap, String outfile,String ftlPath,String ftlName) throws UnsupportedEncodingException {
        //dataMap 要填入模本的数据文件
        //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
        //这里我们的模板是放在template包下面
//        configuration.setClassForTemplateLoading(this.getClass(), ftlPath);
        Template template = null;
        try {
            //test.ftl为要装载的模板
            // 基于文件系统。 比如加载/home/user/template下的模板文件。
            configuration.setDirectoryForTemplateLoading(new File(ftlPath));
            template = configuration.getTemplate(ftlName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //输出文档路径及名称
        File outFile = new File(outfile);
        Writer out = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outFile);
            OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
            //这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
            //out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            out = new BufferedWriter(oWriter);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        try {
            template.process(dataMap, out);
            out.close();
            fos.close();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws UnsupportedEncodingException {
        String tmpFilePath = "C:"+
                File.separator+"tmp"+File.separator;
        String ftlPath ="C:"+File.separator+"ftl"+File.separator;
        Map<String, Object> dataMap =  new HashMap<>();
        long time = new Date().getTime();
        String ftlFile = "信息表.ftl";
        String outDocFile = tmpFilePath+"信息表"+time+".docx";
//        String outPdfFile = tmpFilePath+"信息表"+time +".pdf";
        // ftl由系统自动带出的数据
        dataMap.put("name","joahyan");
        dataMap.put("birthay","Oct 23th 1995");
        dataMap.put("sex","男");
        dataMap.put("age","24");
        DocUtil docUtil = new DocUtil();
        docUtil.createDoc(dataMap,outDocFile,ftlPath,ftlFile);
    }
}
复制代码

生成的word文件

image

word再转pdf

    	public Result downloadEnglishProficiency(@RequestBody AbilityProofDTO abilityProofDTO) throws IOException {
        AttributeValue attributeValue = attributeValueService.getAttributeByKey("CUHK_OAL_ENGLISH");
        String attachmenturl = attributeValueService.getAttributeByKey("UCM_PRE_DOWNLOAD_URL").getPropertyValue();
        Date currentDate = new Date();
        String birthday = null;
        SimpleDateFormat dateFormat = new SimpleDateFormat("d MMM yyyy", Locale.ENGLISH);
        String folderId = attributeValue.getPropertyValue();
        Integer apId = Integer.parseInt(abilityProofDTO.getApId());
        String itName = null;
        ApplicationVO applicationVO = null;
        if (apId != null) {
            applicationVO = applicationService.queryAllDetails(apId);
            birthday = dateFormat.format(applicationVO.getBirthday());
        } else {
            return ResultUtil.error();
        }
        DocUtil docUtil = new DocUtil();
        DocToPdfUtil docToPdfUtil =new DocToPdfUtil();
        Map<String, Object> dataMap =  new HashMap<>();
        // ftl由系统自动带出的数据
        dataMap.put("CurrentDate",dateFormat.format(currentDate));
        dataMap.put("StudentName",applicationVO.getPinyinName());
        dataMap.put("BirthDay",birthday);
        FileInputStream fileInputStream = null;
        //输入、输出的文件
        String outDocFile = tmpFilePath+"Statement of English Language Proficiency"+currentDate.getTime()+".docx";
        String outPdfFile = tmpFilePath+"Statement of English Language Proficiency"+currentDate.getTime()+".pdf";
        FileUtils fileUtil = new FileUtils();
        File tmpFile = new File(tmpFilePath);
        File outDoc = new File(outDocFile);
        File outPdf = new File(outPdfFile);
        //删除上一次存储的文件和目录
        if (!tmpFile.exists()){
                tmpFile.mkdir();
            } else {
                fileUtil.deleteDirectory(tmpFilePath);
                tmpFile.mkdir();
            }
        try {
            Map<String, String> attrs = new HashMap<String, String>();
            // 生成docx文件
            docUtil.createDoc(dataMap, outDocFile);
            // 返回一个输入流,将文件存入到数据库中
            fileInputStream = DocToPdfUtil.convertDocxToPDF(outDocFile, outPdfFile);
            String attachmentSize = String.valueOf(fileInputStream.available());
            RidcHandler rh = new RidcHandler("sysadmin");
            LocalDate nowDate = LocalDate.now();
            String yearAndMouth = nowDate.toString().substring(0, 7);
            String childFolderId = "";
            List<ContentEntry> folderList = rh.getFileList(folderId, "FOLDER");
            if (null == folderList || folderList.isEmpty()){
                childFolderId = rh.createFolder(yearAndMouth, folderId);
            } else {
                Optional<ContentEntry> childFolder = folderList.stream().filter(
                        folder -> yearAndMouth.equals(folder.getContentName())).findAny();
                if (childFolder.isPresent()){
                    childFolderId = childFolder.get().getContentId();
                } else {
                    childFolderId = rh.createFolder(yearAndMouth, folderId);
                }
            }
            String result = rh.createPublicFile("Statement of English Language Proficiency"+"-"+applicationVO.getStudentId()+"-"+
                    currentDate.getTime()+".pdf", fileInputStream, childFolderId);
            CertificateDTO CertificateDTO = new CertificateDTO();
            CertificateDTO.setCertificateUrl(attachmenturl + result);
            CertificateDTO.setCertificateSize(attachmentSize);
            CertificateDTO.setVoId(abilityProofDTO.getVoId());
            int resultValue = applicationService.updateCertificateUrl(CertificateDTO);
            if (resultValue == 1) {
                return ResultUtil.success("生成英文能力证明成功");
            }
            return ResultUtil.error("生成英文能力证明失败");
        } catch (Exception e) {
            logger.info(e.getMessage());
            return ResultUtil.error("转换失败");
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        }
    }
复制代码