关于Spring应用异步上传文件MultipartFile时报FileNotFoundException

由于自己项目(springboot后端服务)和文档编辑相关,所以会存在大量的文件上传oss操作,过程中存在有大文件的上传,为了不影响体验,后端服务拿到文件流后直接返回成功,然后交给子线程异步调用oss上传服务。

问题

起初测试什么的根本没发现这个问题,感觉也不是必现的。后来在排查其他问题的时候查看系统日志的时候,偶尔会发现一段java.io.IOException:java.io.FileNotFoundException:/home/admin/appName/.default/temp/tomcat.4504264197870423949.7001/work/Tomcat/Localhost/ROOT/upLoad_ff92855a_13c6_49d9_bbdf_1c062fb9bfd9_00000004.tmp(没有那个文件或目录)的错误。

在后端controller入参中是以MultipartFile来包装文件流的。在注释上看的很清楚,会在请求结束后清理掉临时文件。由于我们是调用异步线程来处理最终的文件上传,所以当主线程返回时,清理掉文件时,就会报没有那个文件或目录了。在springboot的自动配置模块中,有MultipartAutoConfiguration类会默认加载StandardServletMultipartResolver类作为后续bean的元信息。在初始化web子容器时,会初始化StandardServletMultipartResolver bean作为文件解析器。在org.springframework.web.servlet.DispatcherServlet#doDispatch方法中处理请求时,最终checkMultipart的调用会调用上述加载的解析器进行处理org.springframework.web.multipart.support.StandardServletMultipartResolver#resolveMultipart该实现是将request包装成StandardMultipartHttpServletRequest,由于是非懒解析setMultipartFiles方法是AbstractMultipartHttpServletRequest中的方法,该方法会设值multipartFiles。在doDispatch方法处理完主线程的请求后,就会清理文件,会委托给org.springframework.web.multipart.support.StandardServletMultipartResolver#cleanupMultipart来处理如图,StandardMultipartHttpServletRequest是AbstractMultipartHttpServletRequest的子类,isResolved的判断就是AbstractMultipartHttpServletRequest中的属性multipartFiles是否有值,上述分析是有值的,所以就触发了part.delete。

使用org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.StandardMultipartFile#getBytes方法,该方法会调用org.springframework.util.FileCopyUtils#copyToByteArray生产一个新的字节数组保存数据,以避免原始数据删除之后带来的子线程获取文件失败。

原文 

https://juejin.im/post/5eb404ac6fb9a0437a4d34d9

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 关于Spring应用异步上传文件MultipartFile时报FileNotFoundException

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址