SpringBoot 專案打包後獲取不到resource下資源的解決

Yisany發表於2019-01-06

SpringBoot 專案打包後獲取不到resource下資源的解決

在專案中有幾個檔案需要下載,然後不想暴露真實路徑,又沒有CDN,便決定使用介面的方式來獲取檔案。最初的時候使用了傳統的方法來獲取檔案路徑,發現不行。查詢資料後發現是SpringBoot框架導致的,得用另外的方法:

//聽說在linux系統中會失效。
//不用聽說了,就是會掛,血的教訓
String path = ResourceUtils.getURL("classpath:").getPath();

//此方法返回讀取檔案位元組的方式在linux系統中無異。
InputStream inputStream  = getClass().getClassLoader().getResourceAsStream("RSA/privateKey.txt");

//宣告io的resources物件也可訪問
Resource resource = new ClassPathResource(uploadPath+privateKeyFileName);

// 此方法用來寫檔案或上傳檔案在本專案中指定路徑。
String privateKeyFileStr = request.getSession().
            getServletContext().getRealPath("RSA/privateKey.txt"); 

剛開始的時候用的就是第一種方法,初生牛犢不怕虎吧,說不定在linux上就行呢,本地環境測試通過,然後再上linux測試環境,不出意外,掛了。

//聽說在linux系統中會失效。
//不用聽說了,就是會掛,血的教訓
String path = ResourceUtils.getURL("classpath:").getPath();

乖乖使用其他的方法,這裡選擇使用了第三種方法:

public byte[] downloadServerCrt() {
    try {
        Resource resource = new ClassPathResource("static/syslog/cert/server.crt");
        byte[] bytes = readFileInBytesToString(resource);
        return bytes;
    } catch (Exception e) {
        throw new Exception("下載失敗" + e.getMessage());
    }
}

這裡還有一個坑,也是踩過了才知道,這邊的resource是Resource型別的變數,剛開始我使用了resource.getFile()方法獲取到File物件然後再採用IO流進行操作,即:

File file = resource.getFile();
DataInputStream isr = new DataInputStream(resource.getInputStream());
...

在IDE中執行是完全沒有問題的,但使用mvn打包成jar包後,再執行就會提示ERROR:

java.io.FileNotFoundException: class path resource [static/syslog/cert/server.crt] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/home/admin/dtlog-web/lib/log-web-3.0.2.jar!/static/syslog/cert/server.crt

後來查閱了資料說:一旦打成jar包後,使用File是訪問不到資源的內容的,推薦使用getInputStream()的方法,修改後:

InputStream in = resource.getInputStream();
DataInputStream isr = new DataInputStream(in);
...

測試沒有問題,bug解決。

參考資料

Springboot 訪問resources目錄檔案方式

Classpath resource not found when running as jar

相關文章