Java download Excel table (ajax processing stream file)
Problems encountered:
① Export Excel to process a large amount of data.
② The back-end uses the SXSSFWorkbook export function in Apache POI, and does not use the xlsx.core.min.js front-end export. Considering that the front-end export efficiency will be relatively low, more processing is required One-step data
③ Ajax processes the file stream. This should be used not only to export excel files, but also to process other files.
Technology: HTML, CSS, JavaScript, SpringBoot
- Front end ajax part of the code logic:
/**
* handlePrefix,handleNext这两个参数是函数,用来做额外的处理,前一个是下载前处理函数,下载完成之后处理函数
*/
function export(handlePrefix,handleNext){
//准备下载时处理
if(handlePrefix){
handlePrefix();
}
let param = {
};
for (let key in searchArgs) {
param[key] = searchArgs[key];
};
let p = "";
for (let i in param) {
if (param[i] != undefined && param[i] != null && param[i] != "") {
p = p + i + "=" + param[i] + "&";
}
}
p = p.substring(0, p.length - 1);
//以上是进行参数的处理,可进行自定义参数处理
let url = "hpmont/exportHistoryFault.mvc?" + p;
//定义下载文件名
let fileName = "xxx.xlsx";
//使用原生创建请求
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
// 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
xhr.responseType = "blob";
xhr.onload = function () {
// 请求完成,进行处理
if (this.status === 200) {
// 返回200
let blob = this.response;
let reader = new FileReader();
reader.readAsDataURL(blob); // 转换为base64,可以直接放入标签href
reader.onload = function (e) {
// 转换完成,创建一个a标签用于下载,处理思路相当于点击a连接进行完成下载。
let a = document.createElement('a');
//下载文件名
a.download = fileName;
a.href = e.target.result;
$("body").append(a); // 修复firefox中无法触发click
a.click();
$(a).remove();
}
};
//下载完成处理
if(handleNext){
handleNext();
}
};
// 发送ajax请求
xhr.send()
}
- The back-end uses SXSSFWorkbook for export operations:
Excel has been exported here as an example, first of all, you have to import it in maven pom.xml:
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
/**
* 导出excel记录
* @param request
* @param response
*/
@RequestMapping(value = "/exportHistoryFault",method= RequestMethod.GET)
public void exportHistoryFault(HttpServletRequest request, HttpServletResponse response) {
Map<String,Object> param = new HashMap<>();
Enumeration enu=request.getParameterNames();
while(enu.hasMoreElements()){
String paraName=(String)enu.nextElement();
param.put(paraName,request.getParameter(paraName));
}
try {
if (param.get("id")==null|| StringUtils.isEmpty(param.get("id").toString())){
param.put("id",getUserId());
}
//查询需要导出的记录结果
Map<String, Object> res=historyInquiryService.findHistoryList(param);
ExportExcel.exportHistoryFault(response,(List<Map<String, Object>>) res.get("rows"));
} catch (Exception e) {
logger.error("导出电梯信息excel出错",e);
e.printStackTrace();
}
}
public class ExportExcel {
private static final Logger logger = LoggerFactory.getLogger(ExportExcel.class);
public static void exportHistoryFault(HttpServletResponse response, List<Map<String, Object>> list) throws IOException {
long begin = System.currentTimeMillis();
logger.info("开始导出故障记录");
OutputStream output = null;
try {
//在内存中保存1000行,超出刷新,使用SXSSFWorkbook导出的效率很高,具我的数据而言,40万条数据五分钟左右
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1000);
//excel表格的底部Sheet名称
SXSSFSheet sxssfSheet = sxssfWorkbook.createSheet("故障记录");
//设置单元格样式们这里不起作用
CellStyle cellStyle = sxssfWorkbook.createCellStyle();
//设置单元格居中,这里不起作用,不知道为什么
cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
//设置指定列的列宽,256 * 50这种写法是因为width参数单位是单个字符的256分之一
sxssfSheet.setColumnWidth(0, 256 * 20);
sxssfSheet.setColumnWidth(4, 256 * 20);
//创建第一行数据,相当于头标题
SXSSFRow headRow = sxssfSheet.createRow(0);
headRow.createCell(0).setCellValue("工号");
headRow.createCell(1).setCellValue("故障代码");
headRow.createCell(2).setCellValue("检修状态");
headRow.createCell(3).setCellValue("故障楼层");
headRow.createCell(4).setCellValue("上报时间");
//设置单元格数据
if (list != null && list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
SXSSFRow bodyRow = sxssfSheet.createRow(i + 1);
bodyRow.createCell(0).setCellValue(list.get(i).get("elevatorNum") == null ? "" : list.get(i).get("elevatorNum").toString());
bodyRow.createCell(1).setCellValue(list.get(i).get("errorCode") == null ? "" : list.get(i).get("errorCode").toString());
if (list.get(i).get("insSts") != null) {
int insSts = Integer.parseInt(list.get(i).get("insSts").toString());
if (insSts == 1) {
bodyRow.createCell(2).setCellValue("检修");
} else if (insSts == 2) {
bodyRow.createCell(2).setCellValue("正常");
} else if (insSts == 0) {
bodyRow.createCell(2).setCellValue("故障");
} else {
bodyRow.createCell(2).setCellValue("-");
}
}else{
bodyRow.createCell(2).setCellValue("-");
}
bodyRow.createCell(3).setCellValue(list.get(i).get("floor") == null ? "" : list.get(i).get("floor").toString());
bodyRow.createCell(4).setCellValue(list.get(i).get("reportTime") == null ? "" : list.get(i).get("reportTime").toString());
}
}
//重置响应,将响应设置为流文件传递到前端
output = response.getOutputStream();
response.reset();
response.setContentType("application/octet-stream");
sxssfWorkbook.write(output);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
output.close();
}
}
long end = System.currentTimeMillis();
logger.info("完成导出故障记录,耗时:{}{}", end - begin, "毫秒");
}
}
Please study the official website for details on word, excel and other related office operations .