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