SpringBoot使用MultiPartFile接收来自表单的file文件,而后进行服务器的上传是一个项目最基本的需求,我之前的项目都是基于SpringMVC框架搭建的,因此在使用SpringBoot的时候进行MultiPartFile上传遇到了坑java
因为我须要对文件进行MIME-TYPE安全校验,因此代码中前后两次调用了MultipartFile的transferTo()方法,在第二次调用的时候报错,提示没法找到.tmp文件(事实上我在本地windows10环境下,两次都没报错,能够正常上传,是在服务器上运行时发现第二次调用报错了,我查了一下,具体缘由没找到,可能和linux的临时文件回收策略有关),如下是报错信息:linux
java.io.FileNotFoundException: /home/app/sxpservice/temp/upload_e46ffe57_8ee6_4353_b533_d57c040bbc60_00000000.tmp (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.<init>(FileInputStream.java:138) at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.getInputStream(DiskFileItem.java:188) at org.apache.catalina.core.ApplicationPart.getInputStream(ApplicationPart.java:100) at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.getBytes(StandardMultipartHttpServletRequest.java:292) at com.suixingpay.fin.pcc.controller.UploadController.in(UploadController.java:54) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) at javax.servlet.http.HttpServlet.service(HttpServlet.java:644) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
注意:这里的报错是提示一个后缀名为.tmp的临时文件找不到,而不是.png之类的(和你上传的文件相同格式)找不到,若是是后者,那么你遇到的是另外一个问题,是location设置问题,具体解决方法能够百度,这里咱们就不讲了web
咱们看一下transferTo()的实现方式能够了解到,其实就是对文件流进行了读取,咱们应该知道,流只能够被读取一次,因此第二次读取的时候确定就报错了,因此我考虑不直接读取流,而是将流复制一份,这时候我想到将第一次调用改成使用FileUtils.copyInputStreamToFile()方法spring
具体使用方式以下:apache
//获取上传的文件名 String fileName = uploadFile.getOriginalFilename(); // 获取文件后缀名 String suffix=fileName.substring(fileName.lastIndexOf(".")); // 用uuid做为文件名,防止生成的临时文件重复 File dest = File.createTempFile(UuidUtils.getUuid(), suffix); // 将上传文件复制到临时文件 FileUtils.copyInputStreamToFile(uploadFile.getInputStream(),dest);
这样就实现了文件流的复制,进而实现文件上传,而且一个流可使用屡次windows
第一次写博客,有不足和错误的地方,欢迎斧正,勿喷~~感谢感谢~tomcat