时间:2021-05-26
需求描述
要求批量导出数据,以excel的格式。
选择方式
前台 + 后台
之前在别的项目中也遇到过导出的问题,解决方式是直接在前台导出将表格导出。
这次没有选择前台导出的方式,是由于需要导出所有的数据,所以考虑直接在后台获取所有的数据,然后就直接导出,最后前台触发导出API。
后台实现
导出使用的是POI,在上一篇文章中,我已做了基本的介绍,这里就不做介绍配置了,参照:POI实现将导入Excel文件
创建表格
首先先建立一张表,这里要建立.xlsx格式的表格,使用XSSFWorkbook:
Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet("new sheet");接着创建表格的行和单元格:
Row row = sheet.createRow(0);row.createCell(0);然后设置表头:
row.createCell(0).setCellValue("学号");row.createCell(1).setCellValue("姓名");row.createCell(2).setCellValue("手机号码");最后获取所有的数据,对应的填写到单元格中:
int i = 1;for (Student student : studentList) { row = sheet.createRow(i); row.createCell(0).setCellValue(student.getStudentNumber()); row.createCell(1).setCellValue(student.getName()); row.createCell(2).setCellValue(student.getPhoneNumber()); i++;}输出
这部分是纠结比较久的,反复试了很多次。
一开始是直接以文件输出流的形式输出的:
FileOutputStream output = new FileOutputStream("test.xlsx");workbook.write(output);这样可以正确生成文件,但是问题是,它会生成在项目的根目录下。
而我们想要的效果是,下载在本地自己的文件夹中。
要解决这个问题,需要添加相应信息,返回给浏览器:
OutputStream fos = response.getOutputStream();response.reset();String fileName = "test";fileName = URLEncoder.encode(fileName, "utf8");response.setHeader("Content-disposition", "attachment;filename="+ fileName+".xlsx");response.setCharacterEncoding("UTF-8");response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");workbook.write(fos);fos.close();后台完成代码:
public void batchExport(HttpServletResponse response) { logger.debug("创建工作表"); Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("new sheet"); logger.debug("获取所有学生"); List<Student> studentList = (List<Student>) studentRepository.findAll(); logger.debug("建立表头"); Row row = sheet.createRow(0); row.createCell(0).setCellValue("学号"); row.createCell(1).setCellValue("姓名"); row.createCell(2).setCellValue("手机号码"); logger.debug("将学生信息写入对应单元格"); int i = 1; for (Student student : studentList) { row = sheet.createRow(i); row.createCell(0).setCellValue(student.getStudentNumber()); row.createCell(1).setCellValue(student.getName()); row.createCell(2).setCellValue(student.getPhoneNumber()); i++; } OutputStream fos; try { fos = response.getOutputStream(); response.reset(); String fileName = "test"; fileName = URLEncoder.encode(fileName, "utf8"); response.setHeader("Content-disposition", "attachment;filename="+ fileName+".xlsx"); response.setCharacterEncoding("UTF-8"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");// 设置contentType为excel格式 workbook.write(fos); fos.close(); } catch (Exception e) { e.printStackTrace(); }}前台实现
在前台调用的时候,也经历了多次失败,google了很多篇文章,各种各样的写法都有,自己也是试了试,前台后台都对照做了很多尝试,但基本都是有问题的。这里我值给出我最后选择配套后台的方法。
// 后台导出路由const exportUrl = '/api/student/batchExport';// 创建a标签,并点击let a = document.createElement('a');document.body.appendChild(a);a.setAttribute('style', 'display:none');a.setAttribute('href', exportUrl);a.click();URL.revokeObjectURL(exportUrl);最后的实现还是一种比较简单的方法,创建了一个a标签,然后隐式点击。
注意到这里我没有使用http请求,主要是他并不能触发浏览器的下载,在发起请求后,并没有正确的生成文件,具体是什么还不清楚。后面弄明白后我会再更新这篇文章。
升级
上面的形式,在导出所有的数据的时候是没有问题的,但是如果我想带一些参数呢?
另外,我们的项目是建立在nginx同源的基础上,一旦出现跨域问题,前台向后台请求,浏览器是不会默认携带Cookie的,每次请求都将会被看作是一个新的请求。
所以上面的解决办法有所限制。
那么,还可以怎么写呢?
file-saver
这里我将借助FileSaver来帮助我在前台生成excel文件。
this.http.get('student/batchExport', { responseType: 'blob'}) .subscribe(data => { let blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'}); saveAs(blob, 'test.xlsx'); });用httpClient发起get请求,声明:响应类型为blob。
blob是一个用来存储二进制文件的对象。
然后创建一个blob对象,类型为excel格式。
最后,利用file-saver中的saveAs函数,将blob对象生成文件名为'test.xlsx'的excel文件。
调整后台
这里后台大部分和前面的是一样的,但是明眼人会发现,前台使用后面的方法后,下面的代码就多余了:
String fileName = "test";fileName = URLEncoder.encode(fileName, "utf8");response.setHeader("Content-disposition", "attachment;filename="+ fileName+".xlsx");response.setCharacterEncoding("UTF-8");response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");是的,我们将这一部分交由前台负责,所以后台对应的这部分就可以删除了,只使用response获取输出流就可以了:
OutputStream fos = response.getOutputStream();workbook.write(fos);fos.close();好了,使用这种方法,我们就可以在发起http请求的时候,添加我们想要的参数了。
总结
我们在google的时候,很多时候,我们并不能一下子就找到我们想要的东西,但是并不是说这在做无用功,因为我们往往会在一些类似的文章中找到灵感。
所以,当我们没有直接找到我们想要的结果的时候,不妨大胆的做一些尝试,因为我们会在一次又一次失败的尝试中,慢慢的了解问题的原理到底是怎么回事。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
整理文档,搜刮出一个Spring实现excel及pdf导出表格的代码,稍微整理精简一下做下分享。excel导出:packagelight.mvc.utils.e
excel的操作,最常用的就是导出和导入,废话不多说上代码。本例使用NPOI实现的,不喜勿喷哈。。。。复制代码代码如下://////导出Excel///////
本文实例为大家分享了Winform实现导入导出Excel文件的具体代码,供大家参考,具体内容如下//////导出Excel文件////////////数据集//
本文实例讲述了JavaScript导出Excel的方法。分享给大家供大家参考。具体实现方法如下:复制代码代码如下:WEB页面导出为EXCEL文档的方法WEB页面
Java中POI导入EXCEL2003和EXCEL2007的实现方法实现代码:importjava.io.FileInputStream;importjava.