关于SpringBoot在MultipartFile上踩过的坑

简介: 记录坑坑历程

一、第一个问题

当excel导入的数据量比较大或者后台操作数据的逻辑耗时比较长,这个时候我们会考虑异步导入

文件异步方法的实现有着几种实现方式,这里通过指定异步线程池实现的,即@Async("线程池名称")标注异步方法。

然而,在经过测试时发现,该标注的注解也都标注了,但是不能实现异步效果。

几经波折,发现异步方法可以调用非异步方法,是可以实现异步效果;

而先是非异步方法调用异步方法,这样就会失效。这里所说的是在同一个java类里面。

而在不同的java类里面,就不存在上面的问题

二、第二个问题

使用了异步方法,通过Controller接收文件参数,service层进行处理,这时Controller已经将执行成功的结果返回,剩下的就是service层中去进行解析入库。结果,万万没想到,在service中报了一个错,就找不到文件

java.nio.file.NoSuchFileException: D:\UserData\Temp\undertow.1407321862395783323.8400\undertow4517937229384702645upload

2.1 Controller中的方法

@PostMapping("/test")
publicR<String>test(MultipartFilefile) {
testService.test(file);
returnR.success("导入成功");
}

2.2 service中的方法

@Async("asyncImportExecutor")
publicvoidtest(MultipartFilefile) {
try {
EasyExcelUtil.read(file.getInputStream(), Test.class, this::executeImport)
                    .sheet().doRead();
    } catch (Exceptionex) {
log.error("[test]异步导入异常:", ex);
    }
}

看到这个异常NoSuchFileException后就一脸懵逼,测试是通过postman进行的,就开始怀疑postman的问题,已经排查后postman、路径啥的都没有问题,异步调用的流程也是ok的


然后就想这个异常的提示,就是找不到文件,根据打印出来的日志去本地也确实没有找到。后来就有了下面的写法

2.3 改进Controller中的方法

@PostMapping("/test")
publicR<String>test(MultipartFilefile) {
try {
testService.test(file.getInputStream());
    } catch (IOExceptione) {
log.error("[test]异常日志:", e);
returnR.fail("导入失败");
    }
returnR.success("导入成功");
}

2.4 改进Service中的方法

@Async("asyncImportExecutor")
publicvoidtest(InputStreamfile) {
try {
EasyExcelUtil.read(file, Test.class, this::executeImport)
                    .sheet().doRead();
    } catch (Exceptionex) {
log.error("[test]异步导入异常:", ex);
    }
}

这样就不报错了。。。

后来就进行debug调试,发现临时文件是controller层中的MultipartFile对象生成,一直在写同步方法,也没注意这个MultipartFile对象会生成临时文件。后来发现这个controller中返回结果后,临时文件也就没有了。

2.5 错误总结

因为使用的是异步方法,这样就会有一个主线程和一个异步线程。在上传文件后会形成MultipartFile类型的实例,同时生成临时文件,此时是在主线程中。MultipartFile的实例交给异步线程处理后,该临时文件会被springboot(spring)销毁,在异步线程中去getInputStream就会出现上面的异常。

而在下面的写法是将文件流作为了入参,就不会产生找不到文件的情况。

三、第三个问题

切面日志打印

3.1 问题描述

最近做的需求,有上传文件参数的情况,即 MultipartFile 的情况

而且大家的系统框架中也有通过类似 @SysLog 注解切面打印入参日志的需要

这时存在 MultipartFile 类型的参数的时候,估计就会遇见这种类似的情况

java.io.FileNotFoundException:

MultipartFile resource [file] cannot be resolved to URL

MultipartFile resource [file] cannot be resolved to absolute file

MultipartFile resource [file] cannot be resolved to absolute file path

可能这个 MultipartFile 这是一个特殊对象的存在吧 ~ ~ ~


通过 Jackson 对 javaBean 序列化 MultipartFile 字段成json字符串的时候,有这个问题

通过 JSONObject 对 javaBean 序列化 MultipartFile 字段成 json 字符串的时候,也会有类似的问题

3.2 借鉴,特殊判断

// 请求参数处理finalMap<String, Object>paraMap=newHashMap<>(16);
if (valueinstanceofMultipartFile) {
MultipartFilemultipartFile= (MultipartFile) value;
Stringname=multipartFile.getName();
StringfileName=multipartFile.getOriginalFilename();
paraMap.put(name, fileName);
}

但是这种是针对这种情况的解决

@GetMapping("/test")
@ResponseBodypublicvoidtest(Queryquery, MultipartFilefile) {
    ...........
return;
}

像这种情况的,依然无法解决,只能是 兵来将挡水来土掩

@GetMapping("/test")
@ResponseBodypublicvoidtest(Queryquery) {
    ...........
return;
}
publicclassQuery {
privateMultipartFilefile;
privateIntegerpage;
privateIntegersize;
// 省略Get、Set..........}

这个时候就只能将参数对象中的参数Field进行逐一 instanceof MultipartFile,万一出现套娃的情况,就~ ~ ~

3.3 最后

要么将这种情况的不再进行入参的打印

要么就进行特殊的判断

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
目录
相关文章
|
存储 前端开发 Java
MultipartFile实现文件上传和下载(Springboot)
MultipartFile实现文件上传和下载(Springboot)
1279 0
Springboot byte[] 转 MultipartFile ,InputStream 转 MultipartFile
Springboot byte[] 转 MultipartFile ,InputStream 转 MultipartFile
1999 0
Springboot Http文件的访问 Url 转换 MultipartFile ,File 转 MultipartFile
Springboot Http文件的访问 Url 转换 MultipartFile ,File 转 MultipartFile
1765 0
java springboot实现上传MultipartFile类型 进行HttpRequest调用传入第三方上传接口
java springboot实现上传MultipartFile类型 进行HttpRequest调用传入第三方上传接口
|
存储 前端开发 Java
springboot 多线程使用MultipartFile读取excel文件内容报错问题
springboot 多线程使用MultipartFile读取excel文件内容报错问题
springboot 多线程使用MultipartFile读取excel文件内容报错问题
|
4月前
|
JavaScript Java 关系型数据库
基于springboot的项目管理系统
本文探讨项目管理系统在现代企业中的应用与实现,分析其研究背景、意义及现状,阐述基于SSM、Java、MySQL和Vue等技术构建系统的关键方法,展现其在提升管理效率、协同水平与风险管控方面的价值。
|
4月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。
|
4月前
|
JavaScript Java 关系型数据库
基于springboot的古树名木保护管理系统
本研究针对古树保护面临的严峻挑战,构建基于Java、Vue、MySQL与Spring Boot技术的信息化管理系统,实现古树资源的动态监测、数据管理与科学保护,推动生态、文化与经济可持续发展。

热门文章

最新文章