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

相关推荐
LAM LAB16 小时前
【WPS】office邮件合并,怎么将数据源excel中的下一条拼接在文档中的下一个位置
excel·wps
SEO-狼术19 小时前
Document Solutions for Excel, .NET
excel
Access开发易登软件2 天前
Access开发一键删除Excel指定工作表
服务器·前端·后端·excel·vba·access·access开发
Saggitarxm2 天前
Golang实现 - 实现只有表头的 Excel 模板,并在指定列添加了下拉框功能。生成的 Excel 文件在打开时,指定列的单元格会显示下拉选项
excel·下拉框选项序列·生成excel模板·下拉框选项
pk_xz1234562 天前
SAP全自动化工具开发:Excel自动上传与邮件通知系统
运维·人工智能·windows·深度学习·分类·自动化·excel
俊昭喜喜里3 天前
Excel——设置打印的区域
excel
开开心心就好3 天前
Excel数据合并工具:零门槛快速整理
运维·服务器·前端·智能手机·pdf·bash·excel
CodeCraft Studio3 天前
Aspose.Cells 应用案例:法国能源企业实现能源数据报告Excel自动化
自动化·excel·能源·aspose·aspose.cells·数据报告
人工智能训练师3 天前
将EXCEL或者CSV转换为键值对形式的Markdown文件
人工智能·excel