Springboot文件上傳出現(xiàn)找不到指定系統(tǒng)路徑的解決
Springboot文件上傳出現(xiàn)找不到指定系統(tǒng)路徑
1、問題描述
關(guān)鍵字:SpringMVC 4.2.4、Spring Boot 1.3.1、Servlet 3.0、文件上傳
報錯信息:
java.io.IOException: java.io.FileNotFoundException: /tmp/tomcat.273391201583741210.8080/work/Tomcat/localhost/ROOT/tmp/source/IMG_20160129_132623.jpg (No such file or directory)
問題源碼:transferTo方法報錯
// 前端傳入mulFileSource // 創(chuàng)建壓縮前源文件 File fileSourcePath = new File("tmp/source/"); File fileSource = new File(fileSourcePath, mulFileSource.getOriginalFilename()); if (!fileSourcePath.exists()) { fileSourcePath.mkdirs(); } // 將接收得圖片暫存到臨時文件中 mulFileSource.transferTo(fileSource);
2、問題分析
首先,看源碼中文件定義,相對路徑,預(yù)期路徑應(yīng)該是項目路徑/tmp/source/,但是報錯確是一個系統(tǒng)臨時文件路徑(tomcat的)。
其次,由于是transferTo方法報錯,因此應(yīng)該是該方法寫入文件時報錯,因此,我們跟入方法源碼。
public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest { //中間代碼省略 /** * Spring MultipartFile adapter, wrapping a Servlet 3.0 Part object. */ @SuppressWarnings("serial") private static class StandardMultipartFile implements MultipartFile, Serializable { //中間代碼省略 @Override public void transferTo(File dest) throws IOException, IllegalStateException { this.part.write(dest.getPath()); package org.apache.catalina.core; /** * Adaptor to allow {@link FileItem} objects generated by the package renamed * commons-upload to be used by the Servlet 3.0 upload API that expects * {@link Part}s. */ public class ApplicationPart implements Part { //中間代碼省略 @Override public void write(String fileName) throws IOException { File file = new File(fileName); if (!file.isAbsolute()) { file = new File(location, fileName); } try { fileItem.write(file); } catch (Exception e) { throw new IOException(e); } } }
源碼一目了然,使用Servlet3.0的支持的上傳文件功能時,如果我們沒有使用絕對路徑的話,transferTo方法會在相對路徑前添加一個location路徑,即:file = new File(location, fileName);。當(dāng)然,這也影響了SpringMVC的Multipartfile的使用。
由于我們創(chuàng)建的File在項目路徑/tmp/source/,而transferTo方法預(yù)期寫入的文件路徑為/tmp/tomcat.273391201583741210.8080/work/Tomcat/localhost/ROOT/tmp/source/,我們并沒有創(chuàng)建該目錄,因此會拋出異常。
3、問題解決方案
使用絕對路徑
修改location的值
這個location可以理解為臨時文件目錄,我們可以通過配置location的值,使其指向我們的項目路徑,這樣就解決了我們遇到的問題。
在Spring Boot下配置location,可以在main()方法所在文件中添加如下代碼:
/** * 文件上傳臨時路徑 */ @Bean MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); factory.setLocation("/app/pttms/tmp"); return factory.createMultipartConfig(); }
SpringBoot 上傳文件時本地路徑無效
SpringBoot 通過網(wǎng)關(guān)Zuul進(jìn)行附件上傳的時候,有時會出現(xiàn)如下錯誤
[Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io .IOException: The temporary upload location [/tmp/tomcat.3814974221022613431.8080/work/Tomcat/localhost/ROOT] is not valid] with root causejava.io .IOException: The temporary upload location [/tmp/tomcat.3814974221022613431.8080/work/Tomcat/localhost/ROOT] is not valid
錯誤產(chǎn)生的原因
1、spring boot的應(yīng)用服務(wù)在啟動的時候,會生成在操作系統(tǒng)的/tmp目錄下生成一個Tomcat.*的文件目錄,用于"java.io.tmpdir"文件流操作
TomcatEmbeddedServletContainerFactory
2、程序?qū)ξ募牟僮鲿r:會生成臨時文件,暫存在臨時文件中;長時間不操作,導(dǎo)致/tmp下面的tomcat臨時文件目錄被刪除,
且刪除的文件不可恢復(fù),上傳文件時獲取不到文件目錄,報錯
解決方式有以下幾點
1.重啟服務(wù);
2.網(wǎng)關(guān)是否引入spring-boot-starter-web依賴,若無,則將其引入;
3、設(shè)置spring.servlet.multipart.enabled:true
4.修改上傳文件默認(rèn)的BaseDir
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot上傳excel并將表格數(shù)據(jù)導(dǎo)入或更新mySql數(shù)據(jù)庫的過程
這篇文章主要介紹了Springboot上傳excel并將表格數(shù)據(jù)導(dǎo)入或更新mySql數(shù)據(jù)庫的過程 ,本文以Controller開始,從導(dǎo)入過程開始講述,其中包括字典表的轉(zhuǎn)換,需要的朋友可以參考下2018-04-04SpringMVC的組件之HandlerExceptionResolver詳解
這篇文章主要介紹了SpringMVC的組件之HandlerExceptionResolver詳解,不管是在處理請求映射(HandlerMapping),還是在請求被處理(Handler)時拋出的異常,DispatcherServlet都會委托給HandlerExceptionResolver進(jìn)行異常處理,該接口只有一個方法,需要的朋友可以參考下2023-10-10MyBatis 實現(xiàn)數(shù)據(jù)的批量新增和刪除的操作
這篇文章主要介紹了MyBatis 實現(xiàn)數(shù)據(jù)的批量新增和刪除的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02使用spring aop統(tǒng)一處理異常和打印日志方式
這篇文章主要介紹了使用spring aop統(tǒng)一處理異常和打印日志方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06MyBatis中執(zhí)行SQL語句的幾種方式總結(jié)
MyBatis是一個優(yōu)秀的持久層框架,它支持定制化SQL、存儲過程以及高級映射,下面這篇文章主要給大家介紹了關(guān)于MyBatis中執(zhí)行SQL語句的幾種方式,需要的朋友可以參考下2024-04-04解析springBoot-actuator項目構(gòu)造中health端點工作原理
這篇文章主要介紹了springBoot-actuator中health端點工作原理,對spring-boot-actuator的項目構(gòu)造,工作原理進(jìn)行了全面的梳理,側(cè)重health健康檢查部分2022-02-02