前言
前面简单的整合了EasyExcel和Minio,业务的需求是希望报表导出的时候可以在文件服务器上保留备份,并将文件路径存入mysql中。这个业务,我的思路是这样的,导出的时候直接调用文件的上传方法,然后接口返回路径,前端直接调用下载接口完成文件的下载。对于简单的数据导出我想着简便点,想用注解的方式来完成。废话不多说,直接上代码
注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExportExl {
String fileName() default "";
ExcelTypeEnum excelType() default ExcelTypeEnum.XLSX;
Class<?> classType();
}
切面:
@Aspect
@Component
public class ExportExlAspect {
@Autowired
private MinioUtils minioUtils;
@Pointcut("@annotation(com.nnm.scaffold.common.annotation.ExportExl)")
public void export() {
}
@Around("export() && @annotation(exportExl)")
public Object handle(ProceedingJoinPoint point, ExportExl exportExl) {
//获取文件名
String fileName = exportExl.fileName();
if (StringUtils.isBlank(fileName)) {
fileName = IdUtil.randomUUID();
}
ExcelTypeEnum excelTypeEnum = exportExl.excelType();
if (excelTypeEnum == null) {
excelTypeEnum = ExcelTypeEnum.XLSX;
}
//获取导出类型
Object result = null;
try {
result = point.proceed();
} catch (Throwable e) {
throw new BusinessException("查询数据异常!");
}
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
try {
this.setExcelRespProp(response, fileName, excelTypeEnum);
} catch (UnsupportedEncodingException e) {
throw new BusinessException("导出数据编码异常!");
}
try {
// 创建临时文件
String uuid = IdUtil.randomUUID();
File temp = File.createTempFile(uuid, excelTypeEnum.getValue());
EasyExcel.write(temp)
.head(exportExl.classType())
.excelType(excelTypeEnum)
.sheet(fileName)
.doWrite((Collection<?>) result);
FileInputStream inputStream = new FileInputStream(temp);
fileName = FileUtils.datePath() + "/" + fileName + System.currentTimeMillis() + excelTypeEnum.getValue();
minioUtils.uploadFile("scaffold", fileName, inputStream);
//立即删除文件
inputStream.close();
temp.delete();
result = fileName;
} catch (IOException e) {
throw new BusinessException("导出数据异常!");
} catch (Exception e) {
throw new BusinessException("导出数据异常");
}
return result;
}
/**
* 设置excel下载响应头属性
*/
private void setExcelRespProp(HttpServletResponse response, String rawFileName, ExcelTypeEnum excelTypeEnum) throws UnsupportedEncodingException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + excelTypeEnum.getValue());
}
}
FileUtils
public class FileUtils {
/**
* 编码文件名
* 日期路径 + UUID
*/
public static final String extractUploadFilename(MultipartFile file)
{
String fileName = file.getOriginalFilename();
String extension = FilenameUtils.getExtension(fileName);
fileName = datePath() + "/" + UUIDUtils.fastUUID().toString(true) + "." + extension;
return fileName;
}
/**
* 日期路径 即年/月/日 如2018/08/08
*/
public static final String datePath() {
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
}
excel导出接口:
@GetMapping("/downloadexcel.do")
@ApiOperation(value = "excel下载接口")
@ExportExl(fileName = "汇总表", classType = Student.class)
public Object getExcel() {
List<Student> list = data();
return list;
}
ExportExl有两个属性,fileName 表的名字,classType 实体类。
结果:
之所以想用注解,实现让简单的文件导出可以变得简单,更加关注在业务上,当然复杂的业务场景不一定都可以使用注解,还是要根据实际情况来。目前的工作有挺多报表的导出功能,如若有碰到好玩的东西,后面还是会记录的。