springboot实现查询数据以图片形式导出+图片下载

背景:周二下午业务部门提需求,胶东机场出口货物需要.jpg格式空运清单,挺急的。那就啥也别说了,会不会做的赶紧做吧,于是,周三下午做完测试OK,等业务部门下班后更新服务。周四上午做了份操作流程文档告诉业务部门可以用了,没过两个小时,就说改换Excel导出数据了,好家伙,直呼 好家伙 !也没啥事,就当锻炼自己了吧。在此记录一下这两天的成果,自己备份同时也分享一下。

 经过查找资料,找到的可行方案如下:

将数据库查出来的数据,填充到freemarker模板中生成HTML文件,再将HTML文件转成.jpg图片,nice!

一顿操作猛如虎,步骤如下:

1.添加Maven依赖:

        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>core-renderer</artifactId>
            <version>R8</version>
        </dependency>
        <dependency>
            <groupId>com.github.xuwei-k</groupId>
            <artifactId>html2image</artifactId>
            <version>0.1.0</version>
        </dependency>
        <!-- freemarker模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

2.新增freemarker相关配置

spring.freemarker.cache = false
spring.freemarker.charset = UTF-8
spring.freemarker.check-template-location = true
spring.freemarker.expose-request-attributes = true
spring.freemarker.request-context-attribute = request
spring.freemarker.content-type = text/html
spring.freemarker.content-template-loader-path = classpath:/templates

或者:

spring:
  freemarker:
    cache: false
    charset: UTF-8
    check-template-location: true
    expose-request-attributes: true
    request-context-attribute: request
    content-type: text/html
    content-template-loader-path: classpath:/templates

以上为不同的两种形式,作用相同,根据自己代码类型使用。

3.定义模板文件declare.ftl,路径为/templates下面。

<html>
<head>
    <style>
    </style>
</head>

<body>

<h4 style="text-align:center;">
    <span >主单号:${model[0].billNo!""}</span>
</h4>
<p>
<table style="width:100%;margin-top:5px;" cellpadding="2" cellspacing="0" border="1" bordercolor="#000000">
    <tbody>
    <tr>
        <td style="text-align:center;">编号</td>
        <td style="text-align:center;">分运单号</td>
        <td style="text-align:center;">件数</td>
        <td style="text-align:center;">币制代码</td>
        <td style="text-align:center;">订单毛重</td>
        <td style="text-align:center;">商品名称</td>
        <td style="text-align:center;">HS编码</td>
        <td style="text-align:center;">数量</td>
        <td style="text-align:center;">金额</td>
    </tr>

    <#if model?? && model?size gt 0>
        <#list model as item>
            <tr>
                <td style="text-align:center;">${item_index+1}</td>
                <td style="text-align:center;">${item.logisticsNo!""}</td>
                <td style="text-align:center;">${item.piecesNum!""}</td>
                <td style="text-align:center;">${item.currCode!""}</td>
                <td style="text-align:center;">${item.weight!""}</td>
                <td style="text-align:center;">${item.goodsName!""}</td>
                <td style="text-align:center;">${item.hsCode!""}</td>
                <td style="text-align:center;">${item.number!""}</td>
                <td style="text-align:center;">${item.worth!""}</td>
            </tr>
        </#list>
    </#if>

    </tbody>
</table>
<br />
</p>
</body>
</html>

 4.创建FreemarkeTools工具类,用于数据转HTML、HTML转图片

package com.cg.oms.core.utils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.xhtmlrenderer.swing.Java2DRenderer;
import org.xhtmlrenderer.util.FSImageWriter;

import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.Map;

/**
 *
 */
public class FreemarkeTools {

    /**
     * 获取模板转为html
     */
    public static String ftlToString(Map<String,Object> map, String templateName) throws IOException, TemplateException {
        String value = "";
        Configuration configuration = new Configuration();
        Resource resource = new ClassPathResource("templates");
        File sourceFile =  resource.getFile();
        String ftlPath = sourceFile.getAbsolutePath();
        String filName = templateName;
        String encoding = "UTF-8";

        StringWriter out = new StringWriter();
        configuration.setDirectoryForTemplateLoading(new File(ftlPath));
        Template template = configuration.getTemplate(filName,encoding);
        template.setEncoding(encoding);

        template.process(map, out);
        out.flush();
        out.close();
        value = out.getBuffer().toString();
        return value;
    }

    /**
     * html转为图片
     * @param html
     * @param inputFileName
     * @param outputFileName
     * @param widthImage
     * @param heightImage
     * @return
     * @throws IOException
     */
    public static String turnImage(String html, String inputFileName, String outputFileName
            ,int widthImage, int heightImage) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(inputFileName),"UTF-8"));
        bufferedWriter.write(html);
        bufferedWriter.newLine();
        bufferedWriter.flush();
        bufferedWriter.close();

        File f = new File(inputFileName);
        Java2DRenderer renderer = new Java2DRenderer(f, widthImage, heightImage);
        BufferedImage image = renderer.getImage();
        FSImageWriter imageWriter = new FSImageWriter();
        imageWriter.setWriteCompressionQuality(0.9f);
        File imgFile = new File(outputFileName);
        FileOutputStream fout = new FileOutputStream(imgFile);
        imageWriter.write(image, fout);
        fout.close();
        return outputFileName;
    }

}

5.Controller接口:

@Controller
public class BatchController extends BaseController {

    @Autowired
    ProjectConfig projectConfig;

    @Autowired
    private CyyBillService cyyBillService;

    @Autowired
    private ChPictureFileService chPictureFileService;


    /**
     * 生成图片
     */
    @RequestMapping("/batch/exportPicture")
    @ResponseBody
    @RepeatSubmit
    public Dict exportPicture(HttpServletResponse response, @RequestParam String billNo) throws Exception {

        ModelMap modelMap = new ModelMap();
        List<DeclareDetailDTO> details = new ArrayList<>();
        // 根据billNo查询提单信息
        details = cyyBillService.exportPicture(billNo);

        Integer height = 100;
        height += details.size() * 26;
        if (height < 800 ){
            height = 800;
        }
        modelMap.put("model", details);
        String templateName = "declare.ftl";
        String picturePath = "D:/oms/download/downloadPicture/";
        String html = FreemarkeTools.ftlToString(modelMap, templateName);
        String htmlFilePath = picturePath+billNo+".html";
        String imageFilePath = picturePath+billNo+".jpg";
        String imgPath = FreemarkeTools.turnImage(html,htmlFilePath,imageFilePath,1000,height);
        System.out.println("文件生成路径" + imgPath);

        CgAdmin user = ShiroUtils.getSysUser();
        System.out.printf("ID "+user.getId());
        // chPictureFileService.save(billNo, htmlFilePath, user.getId(),0); //保存HTML文件信息
        // chPictureFileService.save(billNo, imageFilePath, user.getId(),1); //保存图片信息

        return Success();
    }

    /**
     * 下载图片
     */
    @RequestMapping("/batch/downloadPicture")
    @ResponseBody
    @RepeatSubmit
    public void downloadPicture(HttpServletResponse response, @RequestParam String billNo) throws Exception {
        // 查询此提单号下的图片信息
        ChPictureFile chPictureFile = chPictureFileService.selectPictureByBillNo(billNo);
        File file ;
        if (null == chPictureFile){
            // 图片信息为空,输出error图片
            ClassPathResource classPathResource = new ClassPathResource("static/download/error.jpg");
            String resource = classPathResource.getURL().getPath();
            file = new File(resource);
            billNo = "error";
        } else {
            // 文件地址
            file = new File(chPictureFile.getPath());
        }
        // 传入输出对象
        FileInputStream fileInputStream = new FileInputStream(file);
        // 设置相关格式
        response.setContentType("application/force-download");
        // 设置下载后的文件名以及header
        response.addHeader("Content-disposition", "attachment;fileName=" + billNo+".jpg");
        // 创建输出对象
        ServletOutputStream outputStream = response.getOutputStream();
        // 常规操作
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fileInputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, len);
        }
        fileInputStream.close();
    }

}

输出效果图:

关于以上,有疑问欢迎留言,大家互相交流学习,更欢迎大牛指正!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值