SpringBoot 打jar包如何解決靜態檔案下載問題
阿新 • • 發佈:2022-03-30
1.問題
SpringBoot專案需要下載一個靜態模板檔案 demo.xlsx,這個檔案放在 resources/static/excel/demo.xlsx 目錄下面。但是專案是以 jar 包的形式線上執行。而jar包作為壓縮包是無法直接獲取的。只能獲取其中的流InputStream,而無法獲取 File型別,而檔案下載時又需要 response.addHeader("Content-Length",String.valueOf(file.length()));
否則檔案下載會報錯,嘗試修復。如下圖所示
所以二者相悖,然後搜尋到雖然 stream.available() 也是可以獲取預估的檔案大小,但是對於網路下載的檔案並不十分準確,受到網路影響很大。而且其返回的是 int型別(-2,147,483,648,2,147,483,647),所以最大也就是 214M的大小,而file.length()返回的是long型別。
綜上所述,搜了一上午,基本上帖子都沒什麼用,直到我搜到下面這個解決辦法,它總結了諸多問題,然後給出一個非常好的解決辦法,見下面。
2.解決辦法
主要就是參考 spring boot中Excel檔案下載踩坑大全 感謝大佬。解決思路就是使用 spring提供的工具類FileCopyUtils.copyToByteArray
一勞永逸的解決問題,適用於小檔案下載。所以我最後的下載工具類程式碼是如下:
public static ResultData downloadFile(HttpServletResponse response, String fileName) { InputStream inputStream = null; OutputStream outputStream = null; try { // 直接獲取流 inputStream = FileUtil.class.getClassLoader().getResourceAsStream("static/excel/" + fileName); response.setContentType("application/octet-stream"); String name = java.net.URLEncoder.encode(fileName, "UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLDecoder.decode(name, "ISO-8859-1") ); outputStream = response.getOutputStream(); if( inputStream != null) { // 呼叫工具類 byte[] results = FileCopyUtils.copyToByteArray(inputStream); outputStream.write(results); outputStream.flush(); } } catch (IOException e) { log.error("檔案下載失敗, e"); } finally { IOUtils.closeQuietly(outputStream); IOUtils.closeQuietly(inputStream); } // ResultData是通用返回類 return new ResultData(200, "操作成功"); }
問題解決