問題描述
Spring Boot應用(使用默認的嵌入式Tomcat)在上傳文件時,偶爾會出現上傳失敗的情況,后臺報錯日志信息如下:“The temporary upload location is not valid”。
原因追蹤
這個問題的根本原因是Tomcat的文件上傳機制引起的!
Tomcat在處理文件上傳時,會將客戶端上傳的文件寫入臨時目錄,這個臨時目錄默認在/tmp路徑下,如:“/tmp/tomcat.6574404581312272268.18333/work/Tomcat/localhost/ROOT”。
而操作系統對于/tmp目錄會不定時進行清理,如果正好因為操作系統的清理導致對應的臨時目錄被刪除,客戶端再上傳文件時就會報錯:“The temporary upload location is not valid”。
實際上,追蹤一下源碼會發現,如果不明確設置Tomcat的文件上傳臨時目錄,默認讀取的是Servlet上下文對象的屬性“javax.servlet.context.tempdir”值,如下源碼:
- org.apache.catalina.connector.Request
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
private void parseParts( boolean explicit) { //... MultipartConfigElement mce = this .getWrapper().getMultipartConfigElement(); //... // 讀取MultipartConfigElement對象的location屬性 String locationStr = mce.getLocation(); File location; if (locationStr != null && locationStr.length() != 0 ) { location = new File(locationStr); if (!location.isAbsolute()) { location = ( new File((File)context.getServletContext().getAttribute( "javax.servlet.context.tempdir" ), locationStr)).getAbsoluteFile(); } } else { // 如果location屬性值為空,則讀取Servlet上下文對象的屬性“javax.servlet.context.tempdir”值(如:/tmp/tomcat.6574404581312272268.18333/work/Tomcat/localhost/ROOT) location = (File)context.getServletContext().getAttribute( "javax.servlet.context.tempdir" ); } //... } |
解決辦法
既然是因為上傳文件的臨時路徑被刪除導致的問題,就要確保改臨時目錄不會被刪除。
2種解決方法:
(1)通過Spring Boot的配置參數“spring.servlet.multipart.location”明確指定上傳文件的臨時目錄,確保該路徑已經存在,而且該目錄不會被操作系統清除。
1
|
spring.servlet.multipart.location=/data/tmp |
如上所示,將上傳文件的臨時目錄指定到路徑“/data/tmp”下。
實際上,在Spring Boot中關于上傳文件的所有配置參數如下所示:
1
2
3
4
5
6
7
|
# MULTIPART (MultipartProperties) spring.servlet.multipart.enabled= true # Whether to enable support of multipart uploads. spring.servlet.multipart. file -size-threshold=0B # Threshold after which files are written to disk. spring.servlet.multipart.location= # Intermediate location of uploaded files. spring.servlet.multipart.max- file -size=1MB # Max file size. spring.servlet.multipart.max-request-size=10MB # Max request size. spring.servlet.multipart.resolve-lazily= false # Whether to resolve the multipart request lazily at the time of file or parameter access. |
(2)在Spring容器中明確注冊MultipartConfigElement對象,通過MultipartConfigFactory指定一個路徑。
在上述源碼追蹤中就發現,Tomcat會使用MultipartConfigElement
對象的location屬性作為上傳文件的臨時目錄。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/** * 配置上傳文件臨時目錄 * @return */ @Bean public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); // tmp.dir參數在啟動腳本中設置 String path = System.getProperty( "tmp.dir" ); if (path == null || "" .equals(path.trim())) { path = System.getProperty( "user.dir" ); } String location = path + "/tmp" ; File tmpFile = new File(location); // 如果臨時目錄不存在則創建 if (!tmpFile.exists()) { tmpFile.mkdirs(); } // 明確指定上傳文件的臨時目錄 factory.setLocation(location); return factory.createMultipartConfig(); } |
參考
以上就是Spring Boot應用上傳文件時報錯的原因及解決方案的詳細內容,更多關于Spring Boot應用上傳文件時報錯的資料請關注服務器之家其它相關文章!
原文鏈接:https://www.cnblogs.com/nuccch/p/11546494.html