最近項目上用到圖片上傳,一開始我都用的是SpringMVC自帶的MultipartFile來處理的,不須要本身新建流來處理,apache
MultipartFile有個方法是void transferTo(File dest) throws IOException, IllegalStateException;服務器
能夠快速的處理。app
作的項目是SpringBoot、和Spring、SpringMVC、Mybatis框架搭建的,若是使用MultipartFile的transferTo方法,會發現不太穩定。有時候會在執行這個方法時拋出異常,表示文件或者目錄不存在框架
報錯信息這會兒很差找了,運維
但報錯的目錄是Tomcat內部的一個目錄,好像是Tomcat把用本身臨時目錄而後由組合了咱們項目文件落地的目錄去保存問價 這固然後報文件或者目錄不存在。ide
/** * 保存上傳文件到制定目錄地址 * * @param file * 當前上傳那文件 * @param filePath * 檔期保存文件目錄地址(全路徑),帶文件名的目錄地址 * @return 返回當前保存後的文件 * @throws IOException */ public File saveFile(MultipartFile file, String filePath) throws IOException { LOGGER.info("ImageUtil's saveFile 進來了:{}", filePath); File tempFile = new File(filePath); if (!tempFile.getParentFile().exists()) { tempFile.getParentFile().mkdirs(); } if (!tempFile.exists()) { LOGGER.info("filePath exists 時 建立 {}", filePath); tempFile.createNewFile(); } file.transferTo(tempFile); return tempFile; }
深刻到源碼內部,發現是:org.apache.catalina.core.ApplicationPart中的測試
@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); } }
這個方法拋出的錯誤,file.isAbsolute()認爲咱們的目錄不是絕對路徑,而後覺得是相對路徑,再去建立文件,確定會致使報錯。spa
本人親測下來發現Windows下若是保存路徑寫得不正確確定會出錯;好比直接copy Windows目錄下的E:\abc,而應該是寫成:app.comment.image=E:\\abccode
可是在Linux服務器環境下,有時候(機率比較低),也會出現這種狀況;暫時我尚未發現爲何會這樣,可是Linux下偶爾出錯應該也是這個問題blog
記得以前有一次,慕名奇妙圖片上傳失敗,這一塊的代碼沒有動過,爲何會出現這種狀況呢,我仔細查看原來是自從上次發佈以後,忽然之間圖片就不能正常上傳了,因此在沒有深究緣由的狀況下,無奈的對運維說:要不把服務重啓一下,這下還真的邪門了,服務重啓以後,就能夠正常的傳圖了
上次是生產環境的問題,後來在測試環境中無心中也出問題了。最後果斷把這個方法給改掉了;
一勞永逸的解決這個問題:
本身用流來寫:
/** * 保存上傳文件到制定目錄地址 * * @param file * 當前上傳那文件 * @param filePath * 檔期保存文件目錄地址(全路徑),帶文件名的目錄地址 * @return 返回當前保存後的文件 * @throws IOException */ public File saveFile(MultipartFile file, String filePath) throws IOException { LOGGER.info("ImageUtil's saveFile{}: ", filePath); // file.transferTo(tempFile); // return tempFile; File tempFile = new File(filePath); if (!tempFile.getParentFile().exists()) { boolean mkdirs = tempFile.getParentFile().mkdirs(); LOGGER.info("--------建立父目錄:{}", mkdirs); } try (BufferedOutputStream buffStream = new BufferedOutputStream(new FileOutputStream(tempFile))) { byte[] bytes = file.getBytes(); buffStream.write(bytes); buffStream.flush(); } return tempFile; }