Java+pdfjs實現pdf分頁加載(pdf懶加載)


寫在最前

因項目原因,需涉及到pdf在線瀏覽技術,但是少數情況下由於pdf文件過大,會導致系統加載緩慢,影響用戶體驗。因此,實現pdf分頁瀏覽可有效的提高在線瀏覽速度。

技術棧為:SpringBoot、Vue、pdfjs、pdfbox等。

主要核心思路:前端請求時請求頭附帶請求范圍range及讀取大小,后端根據請求頭返回相應的pdf文件流

現存問題:單頁面數據大小無法估量,導致分片大小無法更好的設置(DEFAULT_RANGE_CHUNK_SIZE 值),分頁查看出現問題(如:excel轉pdf后單頁面數據量大導致單頁大小為xxM,此時分頁單詞請求大小必須大於這個值才可實現分頁查看)

后端實現

注:將以下方法作為工具類,然后傳入實際的pdf文件對象即可,控制層不需要做多余處理

涉及依賴

  • common-io:便捷操作IO流,非必選
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

分頁方法

    /**
     * @Date:2022/2/10 14:00
     * @Author:lngrid 分頁加載pdf
     */
    public static void loadPDFByPage(File file, HttpServletResponse response, HttpServletRequest request) {
        BufferedInputStream bis = null;
        OutputStream os = null;
        BufferedOutputStream bos = null;
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            bis = new BufferedInputStream(is);
            os = response.getOutputStream();
            bos = new BufferedOutputStream(os);
            // 下載的字節范圍
            int startByte, endByte, totalByte;
            if (request != null && request.getHeader("range") != null) {
                // 斷點續傳
                String[] range = request.getHeader("range").replaceAll("[^0-9\\-]", "").split("-");
                // 文件總大小
                totalByte = is.available();
                // 下載起始位置
                startByte = Integer.parseInt(range[0]);
                // 下載結束位置
                if (range.length > 1) {
                    endByte = Integer.parseInt(range[1]);
                } else {
                    endByte = totalByte - 1;
                }
                // 返回http狀態
                response.setStatus(206);
            } else {
                // 正常下載
                // 文件總大小
                totalByte = is.available();
                // 下載起始位置
                startByte = 0;
                // 下載結束位置
                endByte = totalByte - 1;
                // 返回http狀態
                response.setHeader("Accept-Ranges", "bytes");
                response.setStatus(200);
            }
            // 需要下載字節數
            int length = endByte - startByte + 1;
            // 響應頭
            response.setHeader("Accept-Ranges", "bytes");
            response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + totalByte);
//            response.setContentType("application/pdf");
            response.setContentType("application/octet-stream");
            response.setContentLength(length);
            // 響應內容
            bis.skip(startByte);
            int len = 0;
            byte[] buff = new byte[1024 * 64];
            while ((len = bis.read(buff, 0, buff.length)) != -1) {
                if (length <= len) {
                    bos.write(buff, 0, length);
                    break;
                } else {
                    length -= len;
                    bos.write(buff, 0, len);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //也可使用try catch關閉IO流
            IOUtils.closeQuietly(bos);
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(bis);
            IOUtils.closeQuietly(is);
        }
    }

前端實現

  1、引入pdfjs

   http://mozilla.github.io/pdf.js/getting_started/#download

   

 

 

   2、解壓文件並存放至vue項目的public路徑下,並將文件夾更名為pdfjs,方便后續調用

    

  3、修改pdfjs配置項(重點)

   pdfjs支持pdf分頁操作,無需單獨再行添加js方法,

   首先,找到viewer.js,搜索disable關鍵詞,在13968行開始的配置

   修改為如下:(注釋說明為個人結合網絡資料及個人理解添加,非官方說明),重點為 disableAutoFetch、disableStream 均改為true,網上資料只修改第一個就行了,但始終不成功,也不知道為啥

   

        "disableAutoFetch": true, //是否禁用自動獲取,true為禁用自動獲取,開啟分頁
        "disableFontFace": false,
        "disableRange": false, //是否禁用range獲取文件,false表示支持分頁請求頭
        "disableStream": true, //分頁關鍵,是否禁用流的形式加載

   然后,找到build/pdf.js文件,尋找  DEFAULT_RANGE_CHUNK_SIZE 配置項,並修改為 65536*16

   

  4、前后端請求調試

  前端使用iframe標簽加載pdf文件,訪問路徑為

  

/public/pdfjs/web/viewer.html?file=后端請求鏈接

常見問題

  • disableStream:按照參考資料來講,不需要修改此配置,所以也未曾嘗試修改此配置,結果一直沒有成功,后來修改后意外發現成功了,然后就是搜索此配置的實際作用,但仍未了解這個配置的實際作用。以下為網絡上的一些參考描述:
  • DEFAULT_RANGE_CHUNK_SIZE的問題:在實際操作時忽略了這個參數的配置,認為也影響不大,但是發現如果為默認值每次請求的大小很小,導致雖然有多個分頁請求,但是pdf文件卻無法成功加載,故嘗試修改為*16后,發現單次請求響應大小為1M,pdf也能成功加載了。

參考鏈接

  


免責聲明!

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



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