Spring Boot應用(使用默認的嵌入式Tomcat)在上傳文件時,偶爾會出現上傳失敗的狀況,後臺報錯日誌信息以下:「The temporary upload location is not valid」。java
這個問題的根本緣由是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」值,以下源碼:spring
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」明確指定上傳文件的臨時目錄,確保該路徑已經存在,並且該目錄不會被操做系統清除。apache
spring.servlet.multipart.location=/data/tmp
如上所示,將上傳文件的臨時目錄指定到路徑「/data/tmp」下。tomcat
實際上,在Spring Boot中關於上傳文件的全部配置參數以下所示:app
# 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屬性做爲上傳文件的臨時目錄。this
/** * 配置上傳文件臨時目錄 * @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(); }
【參考】
https://stackoverflow.com/questions/50523407/the-temporary-upload-location-tmp-tomcat-4296537502689403143-5000-work-tomcat/50523578 The temporary upload location is not valid
https://blog.csdn.net/llibin1024530411/article/details/79474953 SpringBoot項目的The temporary upload location ***is not valid 問題操作系統