想在Java中实现Excel和Csv的导出吗?看这就对了
前言
最近在项目中遇到一个需求,需要后端提供一个下载Csv和Excel表格的接口。这个接口接收前端的查询参数,针对这些参数对数据库做查询操作。将查询到的结果生成Excel和Csv文件,再以字节流的形式返回给前端。
前端拿到这个流文件之后,最开始用ajax来接收,但是前端发送的请求却被浏览器cancel掉了。后来发现,发展了如此之久的Ajax居然不支持流文件下载。后来前端换成了最原始的XMLHttpRequest,才修复了这个问题。
首先给出项目源码的地址。这是源码,欢迎大家star或者提MR。
Csv
新建controller
先来一个简单的例子。首先在controller中新建这样一个接口。
@GetMapping("csv")
public void csv(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String fileName = this.getFileName(request, "测试数据.csv");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
LinkedHashMap<String, Object> header = new LinkedHashMap<>();
LinkedHashMap<String, Object> body = new LinkedHashMap<>();
header.put("1", "姓名");
header.put("2", "年龄");
List<LinkedHashMap<String, Object>> data = new ArrayList<>();
body.put("1", "小明");
body.put("2", "小王");
data.add(header);
data.add(body);
data.add(body);
data.add(body);
FileCopyUtils.copy(ExportUtil.exportCSV(data), response.getOutputStream());
}
其中this.getFileName(request, "测试数据.csv")
函数是用来获取导出文件名的函数。单独提出来是因为不同浏览器使用的默认的编码不同。例如,如果使用默认的UTF-8编码。在chrome浏览器中下载会出现中文乱码。代码如下。
private String getFileName(HttpServletRequest request, String name) throws UnsupportedEncodingException {
String userAgent = request.getHeader("USER-AGENT");
return userAgent.contains("Mozilla") ? new String(name.getBytes(), "ISO8859-1") : name;
}
response.getOutputStream()
则是用于创建字节输出流,在导出csv文件的controller代码结尾,通过工具类中的复制文件函数将字节流写入到输出流中,从而将csv文件以字节流的形式返回给客户端。
当前端通过http请求访问服务器接口的时候,http中的所有的请求信息都会封装在HttpServletRequest
对象中。例如,你可以通过这个对象获取到请求的URL地址,请求的方式,请求的客户端IP和完整主机名,Web服务器的IP和完整主机名,请求行中的参数,获取请求头的参数等等。
针对每一次的HTTP请求,服务器会自动创建一个HttpServletResponse
对象和请求对象相对应。响应对象可以对当前的请求进行重定向,自定义响应体的头部,设置返回流等等。
新建导出工具类
我们新建一个导出工具类,来专门负责导出各种格式的文件。代码如下。
public class ExportUtil {
public static byte[] exportCSV(List<LinkedHashMap<String, Object>> exportData) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedWriter buffCvsWriter = null;
try {
buffCvsWriter = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8));
// 将body数据写入表格
for (Iterator<LinkedHashMap<String, Object>> iterator = exportData.iterator(); iterator.hasNext(); ) {
fillDataToCsv(buffCvsWriter, iterator.next());
if (iterator.hasNext()) {
buffCvsWriter.newLine();
}
}
// 刷新缓冲
buffCvsWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 释放资源
if (buffCvsWriter != null) {
try {
buffCvsWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return out.toByteArray();
}
private static void fillDataToCsv(BufferedWriter buffCvsWriter, LinkedHashMap row) throws IOException {
Map.Entry propertyEntry;
for (Iterator<Map.Entry> propertyIterator = row.entrySet().iterator(); propertyIterator.hasNext(); ) {
propertyEntry = propertyIterator.next();
buffCvsWriter.write("\"" + propertyEntry.getValue().toString() + "\"");
if (propertyIterator.hasNext()) {
buffCvsWriter.write(",");
}
}
}
}
fillDataToCsv
主要是抽离出来为csv填充一行一行的数据的。
运行
然后运行项目,调用http://localhost:8080/csv,就可以下载示例的csv文件。示例如下。
Excel
新建controller
新建下载xlsx文件的接口。
@GetMapping("xlsx")
public void xlsx(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String fileName = this.getFileName(request, "测试数据.xlsx");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
List<LinkedHashMap<String, Object>> datas = new ArrayList<>();
LinkedHashMap<String, Object> data = new LinkedHashMap<>();
data.put("1", "姓名");
data.put("2", "年龄");
datas.add(data);
for (int i = 0; i < 5; i++) {
data = new LinkedHashMap<>();
data.put("1", "小青");
data.put("2", "小白");
datas.add(data);
}
Map<String, List<LinkedHashMap<String, Object>>> tableData = new HashMap<>();
tableData.put("日报表", datas);
tableData.put("周报表", datas);
tableData.put("月报表", datas);
FileCopyUtils.copy(ExportUtil.exportXlsx(tableData), response.getOutputStream());
}
补充工具类
上面新建的导出工具类中,只有导出csv的函数,接下来我们要添加导出xlsx的函数。
public static byte[] exportXlsx(Map<String, List<LinkedHashMap<String, Object>>> tableData) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
HSSFWorkbook workbook = new HSSFWorkbook();
// 创建多个sheet
for (Map.Entry<String, List<LinkedHashMap<String, Object>>> entry : tableData.entrySet()) {
fillDataToXlsx(workbook.createSheet(entry.getKey()), entry.getValue());
}
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
return out.toByteArray();
}
/**
* 将linkedHashMap中的数据,写入xlsx表格中
*
* @param sheet
* @param data
*/
private static void fillDataToXlsx(HSSFSheet sheet, List<LinkedHashMap<String, Object>> data) {
HSSFRow currRow;
HSSFCell cell;
LinkedHashMap row;
Map.Entry propertyEntry;
int rowIndex = 0;
int cellIndex = 0;
for (Iterator<LinkedHashMap<String, Object>> iterator = data.iterator(); iterator.hasNext(); ) {
row = iterator.next();
currRow = sheet.createRow(rowIndex++);
for (Iterator<Map.Entry> propertyIterator = row.entrySet().iterator(); propertyIterator.hasNext(); ) {
propertyEntry = propertyIterator.next();
if (propertyIterator.hasNext()) {
String value = String.valueOf(propertyEntry.getValue());
cell = currRow.createCell(cellIndex++);
cell.setCellValue(value);
} else {
String value = String.valueOf(propertyEntry.getValue());
cell = currRow.createCell(cellIndex++);
cell.setCellValue(value);
break;
}
}
if (iterator.hasNext()) {
cellIndex = 0;
}
}
}
fillDataToXlsx
的用途与csv一样,为xlsx文件的每一行刷上数据。
运行
然后运行项目,调用http://localhost:8080/xlsx,就可以下载示例的csv文件。示例如下。
项目地址
最后再次给出项目地址,大家如果没有理解到其中的一些地方,不妨把项目clone下来,自己亲自操作一波。
参考
这是在解决请求被浏览器cancel掉的过程中,很重要的一个参考,分享给大家。
想在Java中实现Excel和Csv的导出吗?看这就对了的更多相关文章
- SpringBoot中关于Excel的导入和导出
前言 由于在最近的项目中使用Excel导入和导出较为频繁,以此篇博客作为记录,方便日后查阅.本文前台页面将使用layui,来演示对Excel文件导入和导出的效果.本文代码已上传至我的gitHub, ...
- JAVA中生成Excel方法
java 操作 Excel 最常用的就是JXL(java excel api)和POI,今先看下JXL吧.首先可以到 http://www.andykhan.com/jexcelapi/downloa ...
- 用java代码解决excel打开csv文件乱码问题
Java 读取csv文件后,再保存到磁盘上,然后直接用Excel打开,你会发现里面都是乱码. 贴上代码: public class Test { public static void main(S ...
- POI开发:Java中的Excel相关操作
一.Apache POI 1.简介: Apache POI支持大多数中小规模的应用程序开发,提供API给Java程序对Microsoft Office格式档案读和写的功能,呈现和文本提取是它的主要特点 ...
- Java中使用jxl.jar将数据导出为excel文件
Java对Excel文件的读写操作可由jxl.jar或poi.jar实现,这里使用jxl.jar完成对Excel文件的导出. 一.将Excel文件导出在本地 步骤: 创建文件 -> 创建 ...
- Java中读取Excel功能实现_POI
这里使用apache的poi进行读取excel 1,新建javaproject 项目:TestExcel 2,导入包 包下载地址:http://poi.apache.org/download.html ...
- java中解析excel 批量插入数据库
Facade 层 实现类 (@Service("samePeriodModelImportFacade")) 1. 获取cells 的方法 public Cells getCel ...
- java中的excel操作
导入jxl.jar包: 下载个jxl.jar包,然后这个包放在什么位置都行,在你的项目中导入这个包就可以. 具体做法: 项目上右键,点击“属性”, 类别那里选择”库“,点击"添加jar文 ...
- java中的Excel导出功能
public void exportExcel(Long activityId, HttpServletResponse response) throws IOException { // 获取统计报 ...
随机推荐
- Flask消息验证与提示
一,消息提示基本语法. 1,先新建一个Flask工作空间. 2,新建后自动得到一个app.py文件,直接运行可以看到基本效果.然后引入 from flask import flash.使用这个flas ...
- ubuntu 14.04 rabbitmq集群部署
1.准备机器,我这边准备的是三台ubuntu14.04 机器主机名不能相同,不然节点冲突 2.安装rabbitmq 3.修改hosts文件 root@abc-web-04:~# vim /etc/ho ...
- vue 格式化银行卡(信用卡)每4位一个符号隔断
问题 在做银行卡输入框时有一个需求如题,这里举例用-隔断 调查 查看了很多大公司网站的银行卡输入,发现还有有很多缺陷的: 有的是在中间删除,光标会跳到最后: 有的是能删除掉中间隔断符的: 等等,逻辑感 ...
- [AtCoder3856]Ice Rink Game - 模拟
Problem Statement An adult game master and N children are playing a game on an ice rink. The game co ...
- 常见的UI框架
移动端框架 1.Admui 管理系统快速开发框架--http://docs.admui.com/ 为什么选择Admui?代码开源--开放所有源码,不存在任何加密混淆代码,安全全程可控,开箱即用--包含 ...
- Hadoop集群搭建-full完全分布式(三)
环境:Hadoop-2.8.5 .centos7.jdk1.8 一.步骤 1).4台centos虚拟机 2). 将hadoop配置修改为完全分布式 3). 启动完全分布式集群 4). 在完全分布式集群 ...
- 性能测试学习 第九课--LR12中controller基础知识
1.设计手工场景,理解集合点的策略 2.添加load generator 一.controller基础知识 1.controller的原理 通过场景设计来模拟用户的真实操作并调用vugen中的脚本,然 ...
- Golang Go Go Go part3:数据类型及操作
五.Go 基本类型 1.基本类型种类 布尔值: bool 长度 1字节 取值范围 true, false注意事项:不可用数字代表 true 或 false 整型: int/uint 根据运行平台可能为 ...
- android颜色color.xml设置
XML Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...
- 熟悉HBase基本操作
1. ssh localhost start-dfs.sh start-hbase.sh hbase shell create 'Student', 'S_No', 'S_Name', 'S_Sex' ...