1. 程式人生 > 其它 >SpringBoot 打jar包如何解決靜態檔案下載問題

SpringBoot 打jar包如何解決靜態檔案下載問題

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, "操作成功");
}

問題解決