Springboot分布式,excel导出,运用POI导出,前端用的jsp
1.pom.xml
添加POI架包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.15</version>
</dependency>
2.java代码:
@ApiOperation(value = "内窥镜信息,excel导出")
@RequestMapping(value="/excel",method = RequestMethod.POST)
@RequiresPermissions("ewe:eweendscope:read")
@ResponseBody
public String excel(HttpServletResponse response,@RequestBody Pager pager)throws IOException {
response.setCharacterEncoding("UTF-8");
Map<String, Object> result = null;
List
try {
PagerUtil.handleReqParam(pager, upmsApiService);
result = eweEndscopeService.list(pager);
list= (List) result.get("rows");
System.out.println(list);
//创建excel文件
HSSFWorkbook wb = new HSSFWorkbook();
//创建sheet页
HSSFSheet sheet = wb.createSheet("内窥镜信息表");
//创建标题行
HSSFRow titleRow = sheet.createRow(0);
titleRow.createCell(0).setCellValue("SN码(全球唯一标识)");
titleRow.createCell(1).setCellValue("内窥镜RFID");
titleRow.createCell(2).setCellValue("内窥镜编号");
titleRow.createCell(3).setCellValue("卡片序列号");
titleRow.createCell(4).setCellValue("内窥镜类型");
titleRow.createCell(5).setCellValue("内窥镜名称");
titleRow.createCell(6).setCellValue("型号");
titleRow.createCell(7).setCellValue("品牌");
titleRow.createCell(8).setCellValue("价格");
titleRow.createCell(9).setCellValue("组织编号 ");
titleRow.createCell(10).setCellValue("登记时间");
titleRow.createCell(11).setCellValue("使用状态");
//遍历将数据放到excel列中
for (EweEndscopeView scope : list) {
HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum()+1);
dataRow.createCell(0).setCellValue(scope.getScopeNo()==null?"":scope.getScopeNo());
dataRow.createCell(1).setCellValue(scope.getRfidNo()==null?"":scope.getRfidNo());
dataRow.createCell(2).setCellValue(scope.getScopeInnerNo()==null?"":scope.getScopeInnerNo());
dataRow.createCell(3).setCellValue(scope.getRfidNo()==null?"":scope.getRfidNo());
dataRow.createCell(4).setCellValue(EweConstant.EWE_ARRANGEMENT_SCOPE_TYPE_CN.get(scope.getScopeType()));
dataRow.createCell(5).setCellValue(scope.getScopeName()==null?"":scope.getScopeName());
dataRow.createCell(6).setCellValue(scope.getCategory()==null?"":scope.getCategory());
dataRow.createCell(7).setCellValue(scope.getManufacture()==null?"":scope.getManufacture());
dataRow.createCell(8).setCellValue(scope.getPrice()==null?"":scope.getPrice().toString());
dataRow.createCell(9).setCellValue(scope.getUpmsOrganizationId());
dataRow.createCell(10).setCellValue(scope.getCreateTime());
dataRow.createCell(11).setCellValue(EweConstant.EWE_ENDSCOPE_STATUS_CN.get(scope.getScopeStatus()));
}
// 设置下载时客户端Excel的名称
// String filename =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ".xls";
// response.setContentType("application/vnd.ms-excel");
// response.setHeader("Content-disposition", "attachment;filename=" + filename);
// 设置下载时客户端Excel的名称 (上面注释的改进版本,上面的中文不支持)
// response.setContentType("application/octet-stream;charset=utf-8");
// response.setHeader("Content-Disposition", "attachment;filename="
// + new String("内窥镜信息".getBytes(),"iso-8859-1") + ".xls");
// OutputStream ouputStream = response.getOutputStream();
** // wb.write(ouputStream);**
** // ouputStream.flush();**
** // ouputStream.close();**
改为
将response的contentType改为application/x-download
response.setCharacterEncoding("utf-8");
response.setContentType("application/x-download");
String filedisplay = "product.xls";
filedisplay = URLEncoder.encode(filedisplay, "utf-8");
response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay);
OutputStream ouputStream = response.getOutputStream();
wb.write(ouputStream);
ouputStream.flush();
ouputStream.close();
// //新建文件输出流
//FileOutputStream fOut=new FileOutputStream("C:\workspace\bookdata1.xls");
//将数据写入Excel
//wb.write(fOut);
//fOut.flush();
//fOut.close();
//return "C:\workspace\bookdata1.xls";
} catch (Exception e) {
LOGGER.warn("EweEndscopeController list 异常", e);
return "";
}
我用的直接生成file文件,如果用response生成excel文件流,在前端不好转。因为我这个系统前端技术用的老,用的是jsp和bootstarp。因为领导觉得页面上的js导出只能导出当前页面,所以想改成java导出。
说说用用response生成excel文件流我遇到的问题:因为项目的前端查询用的是\(table.bootstrapTable后台接收的是json对象,而且需要将查询出来的导出。所以form表单这排除了。a标签也排除了。我就想着在前端转换,但是转换出的excel是乱码,就失败了。
在这列出,XMLHttpRequest js请求post
//后台生成excel流文件,前端需要用herf链接过
<%--url = "\){basePath}/manage/eweendscope/excel";--%>
//用xmlhttpRequest请求成功但是要将responseType=blob;就是告诉服务器我要接收的是blob字节流,这样才不会前端接受成乱码
url = "${basePath}/manage/eweendscope/excel";
xhr = new XMLHttpRequest();
xhr.open("post", url, true);
var data;
xhr.setRequestHeader("Content-Type", "application/json");
xhr.responseType = 'blob';//告诉服务器我要的数据为blob
var str = JSON.stringify(allData);
xhr.onload = function (oEvent) {
var content = xhr.response;
var elink = document.createElement('a');
elink.download = "内窥镜.xls";
elink.style.display = 'none';
var blob = new Blob([content]);
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
document.body.removeChild(elink);
};
xhr.send(str);
ajax请求方式有点鸡肋,并且是乱码
写在按钮的调用方法中:
\(.ajax({
url : "\){basePath}/manage/eweendscope/excel",// 后台请求的数据
contentType:'application/x-www-form-urlencoded', // 数据格式
responseType: 'blob',
type : "post",// 请求方式
async : false,// 是否异步请求
headers: {
'Content-Type': 'application/json'
},
data : JSON.stringify(allData),// data是传给后台的字段,后台需要哪些就传入哪些
success : function(datas) { // 如果请求成功,返回数据。
// returndata = datas;
// console.log(datas.toString());
// alert("打印成功")
downloadFile(datas);
},
})
function downloadFile(data){
if (!data) {
return;
}
var url = window.URL.createObjectURL(new Blob([data]))
var link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', 'excel1111.xls');
document.body.appendChild(link);
link.click();
}
总结:excel后台好写,但是前端接收不好写,可能是我第一次前后端一起写而且还要有查询条件。