1、需求

需要在后台实时预览每条数据的情况
注:我都是使用模板填充数据生成的,没有编辑Excel样式

2、解决方案

  1. excel转html前端展示
  2. 直接生成Excel并上传到服务器,前端展示

3、上代码

3.1、引入依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.0.0</version>
</dependency>
<!-- easy poi -->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.1.3</version>
    <scope>compile</scope>
</dependency>

3.2、准备Excel模板

在这里插入图片描述
在这里插入图片描述

3.3、Excel转Html

/**
 * 根据ID查看预览某一个信息
 * @param id
 * @param response
 */
@GetMapping("/preview")
public void preview(Integer id, HttpServletResponse response) {
    LambdaQueryWrapper<DemonstrationPlatform> lqw = new LambdaQueryWrapper<DemonstrationPlatform>();
    lqw.eq(DemonstrationPlatform::getId, id);
    //使用准备好的模板
    TemplateExportParams params = new TemplateExportParams("excel/platform.xls");
    Map<String, Object> map = new HashMap<>(16);
    try {
        //数据填充
        List<DemonstrationPlatform> list = demonstrationPlatformService.list(lqw);
        map.put("list", list);
        Workbook excel = ExcelExportUtil.exportExcel(params, map);
        //准备excel转换成html
        ExcelToHtmlParams htmlParams = new ExcelToHtmlParams(excel);
        byte[] bytes = ExcelXorHtmlUtil.excelToHtml(htmlParams).getBytes();
        //将html二进制码输出给浏览器
        response.getOutputStream().write(bytes);
        excel.close();
    } catch (Exception e) {
        logger.info("预览失败 --> {}", e.getMessage());
    }
}

3.4、前端处理响应的html

使用对话框显示

<!-- 详情预览 -->
 <el-dialog title="预览" :visible.sync="contentDialog" width="70%">
     <div v-html="content" id="content"></div>
 </el-dialog>

处理表格过宽的情况,让其在对话框宽100%

#content >>> table {
    width: 100%;
}

获取后端响应的html

preview(id) {
	this.$ajax.get(id).then((res) => {
		if (res === null || res === undefined) return this.$message.error('预览失败!');
		this.content = res;
		//打开对话框
		this.contentDialog = true;
	});
}

3.5、预览文件格式

*注:准备一个空的excel文件,用来装输入的流
我这边把输出流转换成了输入流,并把输入流输入到空文件里,再上传到服务器的

3.5.1、获取excel的文件并转换为MultipartFile用于上传到服务器
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author 阿杰
 * @create 2021-06-03 13:39
 */
public class ExcelUtil<T> {

    /**
     * 生成excel文档数据并转换为上传文件
     * @param t
     * @param templateName
     * @return
     * @throws IOException
     */
    public static<T> MultipartFile getExcelFile(T t, String templateName) throws IOException {
        //获取模板
        TemplateExportParams params = new TemplateExportParams(templateName);
        //创建map存值使用
        Map<String, Object> map = new HashMap<>(16);
        List<T> list = new ArrayList<>();
        //添加数据
        list.add(t);
        map.put("list", list);
        //创建字节输出流
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        //填充模板数据
        Workbook excel = ExcelExportUtil.exportExcel(params, map);
        //获取excel输出流
        excel.write(arrayOutputStream);
        arrayOutputStream.flush();
        //输出流转输出流
        ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(arrayOutputStream.toByteArray());
        InputStreamResource inputStreamResource = new InputStreamResource(arrayInputStream);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStreamResource.getInputStream());
        //获取文件流
        String fileName = "excel/temp.xls";
        ClassPathResource temp = new ClassPathResource(fileName);
        File tempexcelFile = temp.getFile();
        //清空临时文件数据
        clearFile(tempexcelFile);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(tempexcelFile));
        int len;
        byte[] bytes = new byte[1024];
        while ((len=bufferedInputStream.read(bytes)) != -1) {
            bufferedOutputStream.write(bytes, 0, len);
        }
        bufferedInputStream.close();
        bufferedOutputStream.close();
        //获取文件的输入流
        FileInputStream inputStream = new FileInputStream(tempexcelFile);
        //将文件流转换成MultipartFile接口,因为web文件上传需要这个接口 下面这个是它其中的一个实现类
        return new MockMultipartFile("file", tempexcelFile.getName(), "text/plain", IOUtils.toByteArray(inputStream));
    }

    /**
     * 清空文档数据
     * @param tempexcelFile
     * @throws IOException
     */
    private static void clearFile(File tempexcelFile) throws IOException {
        //获取根路径
        FileWriter writer = new FileWriter(tempexcelFile);
        writer.write("");
        writer.flush();
        writer.close();
    }
}
3.5.2、上传并获取到文件路径
/**
 * 获取生成的Excel路径
 * @param demonstrationPlatform
 * @param response
 * @return
 */
private String getExcelUrl(DemonstrationPlatform demonstrationPlatform, HttpServletResponse response) {
    try {
        //根据封装的工具类取得上传文件对象
        MultipartFile excelFile = ExcelUtil.getExcelFile(demonstrationPlatform, "excel/platform.xls");
        //调用oss阿里文件服务的接口,返回文件路径
        return remoteOssService.upload(excelFile).getData();
    } catch (Exception e) {
        logger.info("预览异常 --> " + e.getMessage());
        response.setContentType("application/json;charset=utf-8");
        try {
            response.getWriter().print("预览异常 --> " + e.getMessage());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    return null;
}
3.5.3、在添加或修改时调用上面方法,然后把excelUrl存入数据库
3.5.4、前端实现预览
 //excel预览 Url是后端从数据库拿到的服务器地址  注意url一定是在浏览器可以访问的
 preview(url) {
     if (!url) return this.$message.warning('预览异常!');
     //调用微软的第三方接口显示word、excel、md...... url=服务器地址+url
     window.open("https://view.officeapps.live.com/op/view.aspx?src=" + url, "_blank");
 }

至此就结束啦,这个也是我在工作中遇到的问题。
关于使用流直接上传到服务器,我试了很久没有成果,就放弃了,这种方式是可行的,目前已上线。

Logo

前往低代码交流专区

更多推荐