EasyPoi 模板导出报空指针问题处理

27 篇文章 1 订阅
5 篇文章 0 订阅

一、前言

下图代码是SpringBoot项目controller层中的easypoi模板导出功能。在正常的开发测试过程中,并不会出现问题,但是当我们将其打成jar包放到Linux服务器上时,就会出现NPE(空指针异常),异常为第51行中的Excel模板找不到。

主要原因有两点:

  1. Linux和Window文件系统环境不一致。
  2. springBoot项目打jar包后文件资源加载方式不同,打包后Spring试图访问文件系统路径,但无法访问jar中的路径。 

Spring作者本人回答如下图,

原文:https://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as-jar

导出功能 

Spring作者回答(google翻译)

 

二、解决方案 

可以使用 resource.getInputStream() 获取模板的文档流,重写到tomcat容器中并生成新的模板路径,按新的路径,导出excel即可。

ExcelExportUtils.convertTemplatePath( )  方法代码如下:

/**
 * @Author gmd
 * @Description Excel导出方法
 */
public class ExcelExportUtils {
    /**
     * 模板路径处理,避免出现NPE
     * windows和linux系统不同,且SpringBoot的文件加载方式已有不同,不能简单的使用相对路径
     * @param path excel模板的相对路径
     * @return 重写后的模板路径
     */
    public static String convertTemplatePath(String path) {
        // 如果是windows则直接返回
        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            return path;
        }

        Resource resource = new ClassPathResource(path);
        FileOutputStream fileOutputStream = null;
        // 将模版文件写入到tomcat临时目录
        String folder = System.getProperty("catalina.home");
        File tempFile = new File(folder + File.separator + path);
        // 文件存在时不再写入
        if (tempFile.exists()) {
            return tempFile.getPath();
        }
        File parentFile = tempFile.getParentFile();
        // 判断父文件夹是否存在
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try {
            BufferedInputStream inputStream = new BufferedInputStream(resource.getInputStream());
            fileOutputStream = new FileOutputStream(tempFile);
            byte[] buffer = new byte[10240];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return tempFile.getPath();
    }

}

Excel temp2.xlsx 模板

前端导出代码

<!--HTML代码-->
<button type="button" id="excelOutBtn" class="btn btn-sm bg-orange">
    <i class="fa fa-cloud-upload fa-btn"></i> 导出
</button>

<!--JS-->
// 导出
$("#excelOutBtn").click(function () {
    window.location.href = "${basePath}/aaa/bbb/ccc?id=" + $("#id").val();
});

 

三、后记

至此,通过 resource.getInputStream() 方法我们已经解决了NPE问题。但是存在另一个明显的性能问题,即上述方法 需要生成新的excel模板,重写磁盘,耗时且低效。

而更好的解决方案是通过FreeMarker的excel模板来导出数据。具体方法见本人另一篇博客:

https://blog.csdn.net/qq_41057885/article/details/109682412

easypoi是一个用于ExcelWord文档操作的Java库。它提供了简单易用的API,可以通过模板导出Excel文件。下面是使用easypoi进行模板导出的示例代码: 1. 导入easypoi的maven坐标: ```xml <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.2.0</version> </dependency> ``` 2. 在Spring Boot的配置文件(bootstrap.yml或application.yml)中配置模板的URL: ```yaml easypoi: template: 'http://www.xxx.cn/statics/template/port.xlsx' ``` 3. 使用easypoi进行模板导出: ```java import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.TemplateExportParams; import org.apache.poi.ss.usermodel.Workbook; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.Map; public class TemplateExportDemo { public static void main(String[] args) throws IOException { // 模板文件的URL String templateUrl = "http://www.xxx.cn/statics/template/port.xlsx"; // 下载模板文件 URL url = new URL(templateUrl); URLConnection connection = url.openConnection(); InputStream inputStream = connection.getInputStream(); // 加载模板文件 Workbook workbook = ExcelExportUtil.importExcel(inputStream); // 创建模板参数 TemplateExportParams params = new TemplateExportParams(); params.setSheetNum(0); // 指定导出的Sheet页 // 创建数据模型 Map<String, Object> dataModel = new HashMap<>(); dataModel.put("name", "John"); dataModel.put("age", 25); // 导出Excel文件 FileOutputStream outputStream = new FileOutputStream("output.xlsx"); ExcelExportUtil.exportExcel(params, dataModel, workbook.getSheetAt(params.getSheetNum()), outputStream); // 关闭流 outputStream.close(); inputStream.close(); } } ``` 这段代码会从指定的URL下载模板文件,然后根据模板和数据模型生成新的Excel文件。你可以根据自己的需求修改模板文件和数据模型。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值