赞
踩
最近的工作中遇到了复杂的excel报表导出业务,采用的是用excel模板来实现该业务(可以规避大量勾画excel格式的代码),将excel的模板放在项目的resources目录,遇到相关的一些问题及解决方案。
resources目录下模板的位置:
在本地调试时直接用相对路径(templates/xxx.xlsx)就可以获取到对应的模板信息,调试自测过程都非常easy并愉快。
程序打包发到测试环境上,导出excel都是空模板没有任何数据,查看日志发现是在读取resources目录下的模板报错空指针,关键报错日志如下:
java.io.FileNotFoundException: class path resource [templates/scenery.xlsx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/xxx.jar!/BOOT-INF/classes!/templates/xxx.xlsx
从报错信息可以看出来打包(jar)模板的位置和打包之前位置已经不一样了,jar里面也是没有src这个目录,则相对路径去读取模板当然是拿不到的。
将resources目录的文件上传到服务器上,不从resources目录下读取模板,有2种方式:
- 将文件上传到文件服务(如阿里云OSS),并获取到文件地址,通过流方式读取文件。这种方式需要额外的成本(文件服务器)。
- 在jar运行的服务器上创建目录并存放文件,然后程序里读取相对路径。这种方式不太推荐,不可控因素太多(如被误删、服务搬迁等)。
用ClassPathResource读取到resources目录下文件的流,具体代码如下:
<resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> <include>**/*.yml</include> </includes> <!--是否替换资源中的属性--> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> <!--是否替换资源中的属性--> <filtering>false</filtering> </resource>
ClassPathResource resource = new ClassPathResource("templates/xxx.xlsx");
InputStream inputStream = resource.getInputStream();
但是我excel导出是用的easyPOI,模板导出不支持流,必须得是文件的路径,具体实现的代码如下:
/** * 模板报表导出 * @param type http * @param data 报表信息 */ public static void templateExcelExport(Map<String, Object> data, String type, HttpServletResponse httpServletResponse) throws IOException { //获取模板的位置 ReportExcelEnum reportExcelEnum = ReportExcelEnum.valueOf(type); //获取项目的根目录 String rootPath = System.getProperty("user.dir"); //创建临时的模板存放文件 String path = rootPath +"/" + reportExcelEnum.getValue(); log.info("存放模板目录及模板文件::"+path); //判断模板是否已存放在文件中 File file = new File(path); if(!file.exists()){ log.info("不存在则创建文件:"+path); ClassPathResource resource = new ClassPathResource(reportExcelEnum.getValue()); InputStream inputStream = resource.getInputStream(); saveTempFile(inputStream,file); log.info("模板创建成功!"); } //获取模板 TemplateExportParams params = new TemplateExportParams(path); //获取到 Workbook Workbook workbook = ExcelExportUtil.exportExcel(params, data); //文件名 String fileName = reportExcelEnum.getName() + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()) + ".xlsx"; //导出报表 export(httpServletResponse, workbook, fileName); } private static void saveTempFile(InputStream inputStream, File tempFile) throws IOException { //如果文件的目录不存在 if(!tempFile.getParentFile().exists()){ //创建父目录 tempFile.getParentFile().mkdirs(); } OutputStream os = new FileOutputStream(tempFile); byte[] b = new byte[2048]; int length; while ((length = inputStream.read(b)) > 0) { os.write(b, 0, length); } os.flush(); os.close(); inputStream.close(); }
本篇记录一下读取resources目录下文件问题和解决方案,希望能帮到你。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。