SpringBoot整合Fastexcel/EasyExcel导出Excel导出单个图片

整个工具的代码都在Gitee或者Github地址内

gitee:solomon-parent: 这个项目主要是总结了工作上遇到的问题以及学习一些框架用于整合例如:rabbitMq、reids、Mqtt、S3协议的文件服务器、mongodb、xxl-job、powerjob还有用Docker compose部署各类中间组件。如果大家有什么想要弄成通用组件的,可以给我留言,我可以研究下

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.测试结果

相关推荐
破z晓9 小时前
javascript 导出excel表
开发语言·javascript·excel
Am-Chestnuts13 小时前
豆包多轮回答中的表格导出 Excel:编号、日期与长数字检查
excel
hPw0eKIqD1 天前
使用二次封装的Excel COM 组件操作Excel\WPS ET中的区域、行和列
excel·wps
冰心孤城1 天前
Excel: xls与xlsx格式转换排坑指南
java·前端·excel
金豆呀2 天前
WPS批量提取Word文档内容生成固定格式Excel表格
word·excel·wps
Access开发易登软件2 天前
Access 怎么做前后端分离?用 Web API 读写 SQL Server
前端·数据库·人工智能·microsoft·excel·access
红莲凪是3 天前
使用二次封装的Excel COM 组件操作Excel\WPS ET IExcelRange 高级应用
python·excel·wps
用户298698530143 天前
如何使用免费工具在线将 Excel 转换为 XML 格式
人工智能·后端·excel
开开心心就好3 天前
内存清理工具定时自动清理开机自启动
java·开发语言·elasticsearch·ocr·excel·音视频·big data
开开心心就好3 天前
电脑内存优化工具一键释放内存超简单
java·开发语言·macos·arcgis·ocr·excel·音视频