整个工具的代码都在Gitee或者Github地址内
github:https://github.com/ZeroNing/solomon-parent
需要引入的JAR包(版本根据自身要求使用,本教程用的版本均为最新)
java
<dependency>
<groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId>
</dependency>
1.增加测试类
java
public class Test {
@ExcelProperty(value = "abc",converter = ImageExcelConverter.class)
private InputStream inputStream;
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
}
2.增加Converter转换类
java
public class ImageExcelConverter implements Converter<InputStream> {
@Override
public Class<?> supportJavaTypeKey() {
return InputStream.class;
}
@Override
public WriteCellData<?> convertToExcelData(InputStream value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) throws IOException {
try {
if (ValidateUtils.isEmpty(value)){
return new WriteCellData<>("InputStream为空");
}
byte[] bytes = IoUtils.toByteArray(value);
return new WriteCellData<>(bytes);
}catch (Exception e){
return new WriteCellData<>("InputStream异常");
} finally {
if (value != null) {
value.close();
}
}
}
}
3.增加测试类
java
@RestController
public class TestFileController {
private final FileServiceInterface fileService;
private final Logger logger = LoggerUtils.logger(TestFileController.class);
public TestFileController(FileServiceInterface fileService) {
this.fileService = fileService;
}
@PostMapping("/test")
public void test(@RequestPart(name = "file") MultipartFile file) throws Exception {
String bucketName = "default";
//判断桶是否存在
// boolean bucketExists = fileService.bucketExists(bucketName);
// logger.info("桶:{}{}",bucketExists,bucketExists ? "已存在" : "不存在");
// 上传文件
// FileUpload fileUpload = fileService.upload(file,bucketName);
// 分享URL
// String shareUrl = fileService.share(fileUpload.getFileName(),bucketName,3600L);
// 删除文件
// fileService.deleteFile(fileUpload.getFileName(),bucketName);
// 删除桶
// fileService.deleteBucket(bucketName);
Test test = new Test();
test.setInputStream(file.getInputStream());
List<Object> a = new ArrayList<>();
a.add(test);
fileService.upload(ExcelUtils. export("123.xls","123",Test.class,a),bucketName);
// return new ResultVO<>("123");
// return new ResultVO<String>(shareUrl);
}
其中的FileServiceInterface是属于文件上传可以参考以下链接
SpringBoot整合阿里云、腾讯云、minio、百度云、华为云、天翼云、金山云、七牛云、移动云、网易数帆等等有关于S3协议下文分布式对象存储接口_springboot集成s3-CSDN博客
ExcelUtils代码如下
java
public class ExcelUtils {
private static final Logger logger = LoggerUtils.logger(ExcelUtils.class);
/**
* 导出
* @param excelName 文件名需要带上后缀名
* @param sheetName 表名 不填默认为sheet
* @param clazz 需要导出excel的类,其中ExcelProperty注解国际化是类名+.+字段名组成
* @param data 数据
*/
public static void export(HttpServletResponse response, String excelName, String sheetName, Class<?> clazz, List<?> data, HorizontalCellStyleStrategy cellStyleStrategy, AbstractColumnWidthStyleStrategy columnWidthStyleStrategy) throws Exception {
setHead(response, excelName);
//更新Class注解值
StopWatch stopWatch = new StopWatch();
stopWatch.start();
logger.info("开始更新Class注解值国际化");
updateClassExcelPropertyValue(clazz);
stopWatch.stop();
logger.info("结束更新Class注解值国际化,耗时:{}秒",stopWatch.getTotalTimeSeconds());
//开始导出
stopWatch = new StopWatch();
stopWatch.start();
logger.info("开始导出Excel");
FastExcel.write(response.getOutputStream(), clazz)
.registerWriteHandler(ValidateUtils.getOrDefault(cellStyleStrategy,formatExcel()))
.registerWriteHandler(ValidateUtils.getOrDefault(columnWidthStyleStrategy,new ExcelWidthStyleStrategy()))
.sheet(0,ValidateUtils.getOrDefault(sheetName,"sheet"))
.doWrite(data);
stopWatch.stop();
logger.info("结束导出Excel,耗时:{}秒",stopWatch.getTotalTimeSeconds());
}
/**
* 导出
* @param excelName 文件名需要带上后缀名
* @param sheetName 表名 不填默认为sheet
* @param clazz 需要导出excel的类,其中ExcelProperty注解国际化是类名+.+字段名组成
* @param data 数据
*/
public static void export(HttpServletResponse response, String excelName, String sheetName,Class<?> clazz,List<?> data) throws Exception {
export(response, excelName, sheetName, clazz, data, null, null);
}
/**
* 导出
* @param excelName 文件名需要带上后缀名
* @param sheetName 表名 不填默认为sheet
* @param clazz 需要导出excel的类,其中ExcelProperty注解国际化是类名+.+字段名组成
* @param data 数据
* @return 文件
* @throws Exception
*/
public static MultipartFile export(String excelName, String sheetName, Class<?> clazz,List<?> data,HorizontalCellStyleStrategy cellStyleStrategy,AbstractColumnWidthStyleStrategy columnWidthStyleStrategy) throws Exception {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()){
//更新Class注解值
StopWatch stopWatch = new StopWatch();
stopWatch.start();
logger.info("开始更新Class注解值国际化");
updateClassExcelPropertyValue(clazz);
stopWatch.stop();
logger.info("结束更新Class注解值国际化,耗时:{}秒",stopWatch.getTotalTimeSeconds());
//开始导出
stopWatch = new StopWatch();
stopWatch.start();
logger.info("开始导出Excel");
ExcelWriterBuilder excelWriterBuilder = FastExcel.write(os, clazz).registerConverter(new ImageExcelConverter()).registerWriteHandler(ValidateUtils.getOrDefault(cellStyleStrategy,formatExcel())).registerWriteHandler(ValidateUtils.getOrDefault(columnWidthStyleStrategy,new ExcelWidthStyleStrategy()));
ExcelWriter excelWriter = excelWriterBuilder.build();
ExcelWriterSheetBuilder excelWriterSheetBuilder;
WriteSheet writeSheet;
excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
excelWriterSheetBuilder.sheetNo(0).sheetName(sheetName);
writeSheet = excelWriterSheetBuilder.build();
excelWriter.write(data, writeSheet);
// 必须要finish才会写入,不finish只会创建empty的文件
excelWriter.finish();
stopWatch.stop();
logger.info("结束导出Excel,耗时:{}秒",stopWatch.getTotalTimeSeconds());
byte[] content = os.toByteArray();
//生成文件
try(InputStream is = new ByteArrayInputStream(content);){
return new MockMultipartFile(excelName,excelName, MediaType.MULTIPART_FORM_DATA_VALUE, is);
}
}
}
/**
* 导出
* @param excelName 文件名需要带上后缀名
* @param sheetName 表名 不填默认为sheet
* @param clazz 需要导出excel的类,其中ExcelProperty注解国际化是类名+.+字段名组成
* @param data 数据
* @return 文件
*/
public static MultipartFile export(String excelName, String sheetName, Class<?> clazz,List<?> data) throws Exception {
return export(excelName, sheetName, clazz, data, null, null);
}
private static void updateClassExcelPropertyValue(Class<?> clazz) throws Exception {
for(Field field : clazz.getDeclaredFields()){
String i18nKey = clazz.getSimpleName()+"."+field.getName();
Map<String,Object> annotationNameAndValueMap = new HashMap<>();
String value = I18nUtils.getMessage(i18nKey,(String)null);
if(ValidateUtils.isNotEmpty(value)){
annotationNameAndValueMap.put("value", I18nUtils.getMessage(i18nKey,(String)null));
ClassUtils.updateClassField(field, ExcelProperty.class,annotationNameAndValueMap);
}
}
}
/**
* 设置响应头
*
* @param response 回应的请求数据
* @param fileName 文件名字
*/
private static void setHead(HttpServletResponse response, String fileName) {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding(BaseCode.UTF8);
// 这里URLEncoder.encode可以防止中文乱码
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
}
private static HorizontalCellStyleStrategy formatExcel() {
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillBackgroundColor(IndexedColors.WHITE.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 10);
headWriteCellStyle.setWriteFont(headWriteFont);
// 内容的策略
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
WriteFont contentWriteFont = new WriteFont();
// 字体大小
contentWriteFont.setFontHeightInPoints((short) 10);
contentWriteCellStyle.setWriteFont(contentWriteFont);
// 设置自动换行
contentWriteCellStyle.setWrapped(false);
// 设置垂直居中
contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置水平居中
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
}
}
java
public class ClassUtils {
/**
* 更新Class内注解的值
*
* @param clazz class
* @param fieldName 字段名
* @param annotationClazz 注解类Class
* @param annotationNameAndValueMap 注解内值参数名以及对应修改的值
* @throws Exception
*/
public static <T extends Annotation> void updateClassField(Class<?> clazz, String fieldName, Class<T> annotationClazz, Map<String, Object> annotationNameAndValueMap) throws Exception {
updateClassField(clazz.getDeclaredField(fieldName), annotationClazz, annotationNameAndValueMap);
}
public static <T extends Annotation> void updateClassField(Field field, Class<T> annotationClazz, Map<String, Object> annotationNameAndValueMap) throws Exception {
field.setAccessible(true);
T excelProperty = field.getAnnotation(annotationClazz);
if (ObjectUtil.isEmpty(excelProperty)) {
return;
}
InvocationHandler invocatiOnHandler = Proxy.getInvocationHandler(excelProperty);
Field memberValues = invocatiOnHandler.getClass().getDeclaredField("memberValues");
//通过反射获取memberValues 这个属性是Map类型 存放着所有的属性。
memberValues.setAccessible(true);
Map<String, Object> values = (Map<String, Object>) memberValues.get(invocatiOnHandler);
values.putAll(annotationNameAndValueMap);
}
}
4.测试结果

