Springboot导出PDF文件

需求描述

最近项目有一个需求,需要导出 PDF 文件,由于之前并没有做过这方面的需求,从网上花了很长时间才找到相关的资料。最后采用了aspose.words + freemarker的方式解决的问题,制作 freemarker 模板,将 freemarker 模板转为 word 文件。然后再使用 aspose.words 将 word 文件转为 PDF文件。一开始也尝试过使用 docx4j 将 word 文件转为 PDF,但转完正文中文乱码、还有其他各种格式问题,最后并没有采用。

所需依赖

由于 aspose.words 是破解版,在互联网仓库无法下载,需手动将 jar 包引入本地库,如果公司有私服的话也可以上传到自己公司的私服,引入本地库命令如下:

mvn install:install-file -DgroupId=com.aspose -DartifactId=aspose.words -Dversion=15.8 -Dpackaging=jar -Dfile=aspose-words-15.8.0-jdk16.jar
<!-- freemarker模板引擎,用于定义代码生成模板 -->
<dependency>
	<groupId>org.freemarker</groupId>
	<artifactId>freemarker</artifactId>
	<version>2.3.28</version>
</dependency>

<dependency>
	<groupId>com.aspose</groupId>
	<artifactId>aspose.words</artifactId>
	<version>15.8</version>
</dependency>

制作freemarker模板

在 word 中编写你想要的文档,将 word 文档另存为 xml 格式,将需要注入数据的地方修改为 ${xxx} 格式,并且记住你的字段名,如果有多条数据则添加 <#list userList as user></#list>标签,userList 是 Map 里面的 key。

image-20210402142437815

image-20210402142525047

image-20210402142552739

编辑好之后另存为 .ftl 文件,这就是模板。可以存放到项目里的 resource 下的 templates 文件夹下

image-20210402142741541

word文档生成工具类

package com.cxhello.example.util;

import freemarker.template.Configuration;
import freemarker.template.Template;

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

/**
 * @author cxhello
 * @date 2021/4/2
 */
public class WordUtil {
    
    

    private static final String ENCODING = "UTF-8";

    /**
     * 生成word文档
     * @param templateName
     * @param map
     * @return
     * @throws IOException
     */
    public static File generateWord(String templateName, Map map) throws IOException {
    
    
        Configuration configuration = getConfiguration();
        Template template = configuration.getTemplate(templateName);
        File file = createDoc(map, template);
        return file;
    }

    private static Configuration getConfiguration() {
    
    
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
        configuration.setDefaultEncoding(ENCODING);
        configuration.setClassForTemplateLoading(WordUtil.class, "/templates/");
        return configuration;
    }

    private static File createDoc(Map<?, ?> dataMap, Template template) {
    
    
        String name = "sellPlan.doc";
        File f = new File(name);
        Template t = template;
        try {
    
    
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(new FileOutputStream(f), ENCODING);
            t.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
    
    
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
        return f;
    }

}

word转换PDF工具类

package com.cxhello.example.util;

import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLEncoder;

/**
 * @author cxhello
 * @date 2021/4/2
 */
public class PdfUtil {
    
    

    private static final Logger logger = LoggerFactory.getLogger(PdfUtil.class);

    public static void covertDocToPdf(File file, String fileName, HttpServletResponse response) {
    
    
        response.setContentType("application/pdf");
        try {
    
    
            if (!isWordLicense()) {
    
    
                logger.error("License验证不通过");
            }
            fileName = fileName + ".pdf";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
            FileInputStream fileInputStream = new FileInputStream(file);
            Document doc = new Document(fileInputStream);
            fileInputStream.close();
            doc.save(response.getOutputStream(), SaveFormat.PDF);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (file != null) {
    
    
                file.delete();
            }
        }
    }

    public static boolean isWordLicense() {
    
    
        boolean result = false;
        try {
    
    
            InputStream inputStream = PdfUtil.class.getClassLoader().getResourceAsStream("license.xml");
            License license = new License();
            license.setLicense(inputStream);
            result = true;
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return result;
    }

}

业务类

package com.cxhello.example.controller;

import com.alibaba.fastjson.JSON;
import com.cxhello.example.entity.StandardReportData;
import com.cxhello.example.util.PdfUtil;
import com.cxhello.example.util.WordUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author cxhello
 * @date 2021/4/2
 */
@Controller
public class ExportController {
    
    

    @GetMapping("/exportPdf")
    public void exportPdf(HttpServletResponse response) throws IOException {
    
    
        Map<String, Object> map = new HashMap<>();
        String waterName = "测试水厂";
        map.put("waterName", waterName);
        map.put("time", "2021-03-23");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = simpleDateFormat.format(new Date());
        map.put("date", date);
        File jsonFile = ResourceUtils.getFile("classpath:test.json");
        String json = FileUtils.readFileToString(jsonFile, "UTF-8");
        StandardReportData standardReportData = JSON.parseObject(json, StandardReportData.class);
        map.put("standardReportData", standardReportData);
        File file = WordUtil.generateWord("template.ftl", map);
        PdfUtil.covertDocToPdf(file, waterName + "标准报告", response);
    }

}

代码地址

https://github.com/cxhello/springboot-pdf

参考文章

https://blog.csdn.net/tomcat_zhu/article/details/89397044

https://blog.csdn.net/hunwanjie/article/details/97135633

https://blog.csdn.net/weixin_44723536/article/details/91445959?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&dist_request_id=1328741.37842.16169854640636425&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

https://cloud.tencent.com/developer/article/1639923

https://www.jianshu.com/p/86716c7122ef

猜你喜欢

转载自blog.csdn.net/tianyucxh/article/details/115399357