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 HttpServletResponse 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);
    }
}

需要明確的是:對於下載,不需要返回值。因為,本身就已經把數據輸入到response里面。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM