1、引入包文件
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
当然,如果有引入导入或导出组件,也是可以的。这个不限于Hzero,凡是SpringBoot都是可行的。
2、存放模板
这里要注意一下,我们存放模板可以放在项目的根目录外面,这样可以避免很多访问文件的问题,但是不方便部署,还可以放在项目的resoures
目录下
我在这个目录下创建一个目录temp
,然后将模板存放在这个目录下。
3、创建Controller
我这里使用Post请求,原来使用get请求,前台无法转换格式文件,总是文件受损,换成post就正常了。
@ApiOperation(value = "自定义导出")
@Permission(level = ResourceLevel.ORGANIZATION)
@PostMapping("/excel/export")
public ResponseEntity excelExport(@ApiParam(value = "租户ID", required = true) @PathVariable Long organizationId,
HttpServletResponse response,
@RequestBody SoShipmentDetectionHead soShipmentDetectionHead) {
soShipmentDetectionHead.setTenantId(organizationId);
try {
soShipmentDetectionHeadService.excelExport(response, soShipmentDetectionHead);
} catch (IOException e) {
log.error("导出失败", e);
throw new CommonException("导出失败,请联系管理员");
}
return Results.success();
}
4、创建Service
这里不介绍业务逻辑,只说明技术问题
private void writeExcel(String path, HttpServletResponse response, String ctnNo) throws IOException {
Resource resource = new ClassPathResource(path);
if (resource.isReadable()) {
OutputStream responseOutput = null;
XSSFWorkbook workBook = null;
try (InputStream inputStream = resource.getInputStream()) {
workBook = new XSSFWorkbook(inputStream);
Sheet sheetAt = workBook.getSheetAt(0);
/** 业务逻辑 start **/
SoShipmentDetectionLine line = new SoShipmentDetectionLine();
line.setCartonNo(ctnNo);
List<SoShipmentDetectionLine> lineList = soShipmentDetectionLineRepository.select(line);
SoShipmentDetectionHead head = new SoShipmentDetectionHead();
head.setModType("类型");
head.setCustomer("客户名称");
head.setDate(new Date());
head.setCtnNo(ctnNo);
createHead(lineList, ctnNo, head);
writeSheet(sheetAt, head, lineList);
/** 业务逻辑 end **/
// 设置浏览器解析文件的mime类型,如果js中已设置,这里可以不设置
response.setContentType("application/vnd.ms-excel;charset=gbk");
// 设置此项,在IE浏览器中下载Excel文件时可弹窗展示文件下载
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(ctnNo + ".xlsx", "UTF-8"));
// 允许浏览器访问header中的FileName
response.setHeader("Access-Control-Expose-Headers", "FileName");
// 设置FileName,转码防止中文乱码
response.setHeader("FileName", URLEncoder.encode(ctnNo + ".xlsx", "UTF-8"));
response.flushBuffer();
workBook.write(response.getOutputStream());
} catch (Exception e) {
log.error("error", e);
} finally {
if (null != responseOutput) {
responseOutput.close();
}
if (null != workBook) {
workBook.close();
}
}
} else {
throw new CommonException("文件不存在!");
}
}
这里要知道项目发布时是jar
包形式,一般的读取文件是无法读取jar包里的文件的,这时候要用ClassPathResource
读取文件,文件路径"temp" + File.separator + "testReport.xlsx"
,这样就能读取resoures
目录下的文件了,还有一点要记住,我们读取的文件是.xlsx
,所以要用XSSFWorkbook
创建文件对象,如果是.xls
要用HSSFWorkbook
创建对象。这非常重要,否则文件会损坏。