SpringBoot文件上传丢失的采坑经历 | 您所在的位置:网站首页 › 文件上传漏洞找不到路径了 › SpringBoot文件上传丢失的采坑经历 |
关键词:SpringBoot文件上传、文件上传丢失、MultipartFile、transferTo 本人小白一个,学习java没有多长时间,很多问题可能比较幼稚,分享这些经历主要是想和我一个水平的小白共同交流提高,在这个过程中有什么问题也欢迎留言讨论。 最近在练习SpringBoot文件上传,在调用MultipartFile的transferTo方法的时候,文件保存成功,系统也没有任何报错,但就是在自己指定的位置找不到想要的文件,为了搞清楚我的文件被SpringBoot搞到哪里去了,通过跟踪源码,我发现了一个大坑,具体是啥,且听我慢慢道来。 1. 测试环境搭建 1.1 新建一个SpringBoot项目 1.2 配置项目及代码准备 文件上传配置application.properties: spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.file-size-threshold=10MB java测试代码1.3 测试(用绝对路径,完美通过) 2. 采坑过程(用相对路径) 在上述代码运行成功后,我想通过相对路径,把文件上传到当前项目的文件夹内,所以对代码进行了修改(把绝对路径去掉了): @Slf4j @RestController @RequestMapping("/upload") public class FileUploadController { @PostMapping(value = "/pic", consumes = "multipart/form-data") public String uploadPic(MultipartFile file) throws IOException { log.info("入参信息:{},{},{}", file.getContentType(), file.getSize(), file.getOriginalFilename()); // File dest = new File("D://tmp//" + file.getOriginalFilename()); File dest = new File(file.getOriginalFilename()); file.transferTo(dest); return dest.getAbsolutePath(); } }测试结果:可以正常返回,但是对应的位置,没有文件,也不知道文件去哪里了!!! 3. 原因分析 想知道文件被SpringBoot搞到哪里去了,只能老老实实的跟踪一下源码了:Debug启动 --> 打断点 --> 上传文件 --> 跳转到兴趣点 进入到transferTo方法内4. GitHub沟通过程 我觉得有可能是个bug,所以将疑问提在git上,经过了漫长的等待,有了回复:https://github.com/spring-projects/spring-framework/issues/27079。 但从回复结果来看,当用相对路径进行文件存储时,他们故意将文件存储在了一个临时位置,他建议我用绝对路径。最终回复结果并没有解决我的最大疑问:如果用户使用的是一个相对路径,为什么不给一个友好提示就把文件偷梁换柱弄到了一个他们指定的临时位置了呢?作为一个小白还是有点心虚,所以也就没再追问。 在poutsma的回复中,提到了一个#09822的issus,这里边把我认为是bug的代码的来龙去脉说的很清楚。链接:https://github.com/spring-projects/spring-framework/issues/19822 我再次跟踪了一下源码,把这个巨坑的临时位置共享出来(***是一些随机数字或者和用户名相关的路径): // linux location = /tmp/tomcat.***/work/Tomcat/localhost/ROOT // windows location = C:\Users\***\AppData\Local\Temp\tomcat.***\work\Tomcat\localhost\ROOT5. 解决方案 既然人家也说了,就是这样设计的(突然想起抖音里的一个段子),那只好接受了。那我还想文件上传怎么办呢: 1. 用绝对路径(废话。。。): 就像我最开始演示的那样,给个绝对路径就得了。但是也有一个点需要注意,开发是在windows下,我们如果是真实的项目,是运行在linux系统下,这个时候就需要先判断一下运行环境,基于环境的不同,确定是否需要带盘符(比如D://xxx或者//xxx)。 2. 用相对路径,在源代码中找替代方案(5.1以后): 如下图所示,transferTo有个重载方法,参数类型是Path,代码就一行,基于直觉判断,这个方法靠谱。验证后发现确实有效,但注意,这个方法是5.1以后才有的,如果项目是5.1以前的版本,怎么办呢!!!还用想吗,直接用方法里边的代码呗。。。反正就一行,还是调用了人家的工具类。。。 上代码(Path这个接口很有意思,也值得仔细研究一下): @PostMapping(value = "/video", consumes = "multipart/form-data") public String uploadVideo(MultipartFile file) throws IOException { String uploadFileName = file.getOriginalFilename(); FileSystem fileSystem = FileSystems.getDefault(); Path path = fileSystem.getPath("file", uploadFileName); Path parent = path.getParent(); File filePath = parent.toFile(); if (!filePath.exists()) { filePath.mkdirs(); } File newFile = path.toFile(); file.transferTo(path); return newFile.getAbsolutePath(); }3. 在poutsma 的回复中他提到“override the configuration in your container”,肯定也可以,只是我是个小白,不知道如何操作! 6. 总结 没啥好总结的,说点废话吧。在刚开始学java的时候,遇到很多问题都是首先问百度、谷哥,有的时候,他们也不是万能的,还得积极学习源码,遇到问题养成从源码中找解决方案的习惯。这段时间通过阅读源码,确实给自己带来了不少收货,别的不说,人家开发好的工具类,多用几个放在自己的代码里,立马逼格上升一个档次。 |
CopyRight 2018-2019 实验室设备网 版权所有 |