中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

文件預覽PDF.js使用技巧有哪些

發布時間:2023-03-06 17:17:38 來源:億速云 閱讀:162 作者:iii 欄目:開發技術

這篇文章主要講解了“文件預覽PDF.js使用技巧有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“文件預覽PDF.js使用技巧有哪些”吧!

    Pdf.js有兩種使用方式

    在這次的項目中用到了pdf文件的預覽功能,選擇了pdf.js去預覽pdf文件,實現滑動展示所有的pdf

    • 通過 npm 下載

    • 直接下載 pdf.js 庫,當作靜態資源使用

    把pdf.js當作靜態資源使用

    最開始我采取的是把pdf.js當作靜態資源使用,使用方法如下:

    • 官網下載后解壓項目得到 pdf.js

    • 放到項目文件夾 /public/static/ 下

    • 直接將 web/viewer.html 后面的 file 跟上自己自己的 pdf 文件即可

        contentUrl.current = content.includes("pdf")
        ? `/static/pdfjs-3.1.81-dist/web/viewer.html?file=${content}`
        : content;
        <iframe src={contentUrl.current}></iframe>

    使用靜態資源時,如果需要更改他的默認樣式需要自己手動改源代碼

    同時可能我們遇到了跨域問題,我們需要在源碼中的判斷跨域代碼注釋掉

    文件預覽PDF.js使用技巧有哪些

    使用靜態資源的問題是在移動端不能手勢放大縮小,需要我們自己編寫代碼然后修改源代碼強制放大縮小

    這種方式不細講,網上很多使用方式都是通過使用靜態資源,可以自行去查看,這里只講一個大概。

    npm下載,通過import使用

    方法如下:

    npm install pdfjs-dist
    const contentRef = useRef<HTMLDivElement | null>(null);
    useEffect(() => {
    //content就是 iframe 請求的url,這里是因為我的項目里面需要判斷下他url是否涵蓋了pdf
    //如果涵蓋了才使用pdf.js
      content.includes('pdf')
      //重點是 loadPdf() 這個函數,就是我們使用 pdf.js 的函數
        ? loadPdf(contentRef.current, content, loadingRef.current)
        : null;
    }, [content]);
    <div className="content-wrapper" ref={contentRef}>
      {content.includes('pdf') ? null : <iframe src={content}></iframe>}
      <div className="loading" ref={loadingRef} style={{ display: 'none' }}></div>
    </div>
    import * as pdf from 'pdfjs-dist';
    import pdfWorker from 'pdfjs-dist/build/pdf.worker.js?url';
    pdf.GlobalWorkerOptions.workerSrc = pdfWorker;
    /**
     * @desc 使用pdf.js加載pdf
     * @param contentDom
     * @param url
     */
    export const loadPdf = async (
      contentDom: HTMLDivElement | null,
      url: string,
      loadingDom: HTMLDivElement | null
    ) => {
    //得到請求的 pdf 文件
      const loadingTask = pdf.getDocument({
        url: url,
        disableRange: true
      });
      //loading效果,下載pdf過程中展示loading
      loadingTask.onProgress = () => {
        if (loadingDom) {
          loadingDom.style.display = 'block';
        }
      };
      loadingTask.promise.then((pdfDoc) => {
      //下載完成時,loading消失
        if (loadingDom) {
          loadingDom.style.display = 'none';
        }
        //得到 pdf 總頁數
        const totalPages = pdfDoc.numPages;
        for (let i = 1; i <= totalPages; i++) {
          pdfDoc.getPage(i).then((page) => {
            const canvas = document.createElement('canvas');
            canvas.setAttribute('id', `the-canvas${i}`);
            const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
            const dpr = window.devicePixelRatio || 1;
            const scaledViewport = page.getViewport({ scale: 1 });
            canvas.height = Math.floor(scaledViewport.height * dpr);
            canvas.width = Math.floor(scaledViewport.width * dpr);
            canvas.style.width = document.body.clientWidth + 'px';
            canvas.style.height =
              document.body.clientWidth / (canvas.width / canvas.height) + 'px';
            const transform = dpr !== 1 ? [dpr, 0, 0, dpr, 0, 0] : undefined;
            const renderContext = {
              canvasContext: ctx,
              viewport: scaledViewport,
              transform: transform
            };
            page.render(renderContext);
            contentDom?.appendChild(canvas);
          });
        }
      });
    };

    上面的代碼展示了我使用pdf.js的整個使用過程,主要思路是先獲取到pdf文件,然后得到總頁數后通過生成響應頁數的canvas,然后再渲染到頁面上展示pdf

    這里需要注意的是scaledViewport.height得到的是你的pdf文件本身的寬高,我們需要通過這個寬高進行適配我們自己的屏幕,同時需要保證他的清晰度,所以我們需要保證canvas兩個寬高的尺寸是一致的。

    canvas 本身有兩個寬高,標簽的 width 和 height 是繪畫區域實際寬度和高度,繪制的圖形都是在這個上面。而 style 的 width 和 height 是 canvas 在瀏覽器中被渲染的高度和寬度,如果 canvas 標簽中沒有定義 width 和 height 時,默認會給寬 300 高 150,所以就出現了拉伸的效果,不想用默認的寬高的話,盡量在標簽中寫上寬高的屬性。

    所以,如上面的代碼一樣,寬度就是整個屏幕的寬度,但是每個pdf頁面的高度,需要保證和canvas.width/canvas.height的尺寸一致

    canvas.style.height = document.body.clientWidth / (canvas.width / canvas.height) + 'px';

    這樣就能展示pdf文件了

    這里又存在一個問題,文件過大,而pdf.js的渲染原理是需要將整個pdf文件下載下來后,再進行展示,這就導致了白屏的時間過長,用戶體驗感不好,然后我們就想到了分片下載

    我們需要在 getDocument()這個api上增加一些配置

    const loadingTask = pdf.getDocument({
    		url: url,
    		//disableRange: true,  
    		rangeChunkSize: 65536 * 16,
    		disableAutoFetch: true
    	});

    分片下載還有一個很重要的點,就是需要判斷下你訪問的pdf是否支持分片下載,使用了分片下載的請求是后續會通過你的分片大小發送206請求

    HTTP206狀態碼代表的意思是 請求已成功處理,但僅返回了部分內容,即 HTTP 206 Partial Content 響應狀態。

    HTTP 206 (Http Status Code 206) 狀態是HTTP協議的一種響應碼,是我們請求訪問網站時,服務器端返回的2xx 成功狀態系列響應碼之一。

    文件預覽PDF.js使用技巧有哪些

    查看是否支持分片下載

    文件預覽PDF.js使用技巧有哪些

    需要有這個響應頭才是支持分片下載 accept-range:bytes

    但后面我們遇到一個問題:我們的pdf鏈接存在這個響應頭,但卻不支持分片下載,后面通過對比發現是這個響應頭 access-control-expose-headers 的問題

    響應標頭 Access-Control-Expose-Headers 允許服務器指示哪些響應標頭應該對瀏覽器中運行的腳本可用,以響應跨源請求。

    我們最開始這個響應頭里面的內容沒有Access-Control-Expose-Headers,意味著就算存在 accept-range 這個響應頭,瀏覽器也不可用,所以在后面我們添加上這個響應頭的內容后就可以使用分片下載了。

    API(記錄一下,防止忘記)

    這個api來源于掘金的某位大佬

    屬性說明類型默認值
    屬性說明類型默認值
    worker用于加載和解析 PDF 數據的工作器PDFWorker-
    withCredentials指示是否應使用 cookie 或授權標頭等憑據發出跨站點訪問控制請求。Booleanfalse
    verbosity控制日志記錄級別;應該使用 VerbosityLevel 中的常量Number-
    useWorkerFetch在讀取 CMap 和標準字體文件時啟用在工作線程中使用 Fetch API。當為“true”時,會忽略“CMapReaderFactory”和“StandardFontDataFactory”選項。 Web 環境中的默認值為 true,Node.js 中的默認值為 falseBoolean-
    useSystemFonts是否使用系統字體Booleanfalse
    urlPDF的url地址String  URL
    stopAtErrors拒絕某些方法,例如getOperatorList、getTextContent 和 RenderTask,當相關的 PDF 數據無法成功解析時,而不是嘗試恢復任何可能的數據Booleanfalse
    standardFontDataUrl標準字體文件所在的地址。包括尾部斜杠String-
    StandardFontDataFactory讀取標準字體文件時將使用的工廠。提供自定義工廠對于沒有 Fetch API 或 XMLHttpRequest 支持的環境很有用,例如 Node.jsObject{DOMStandardFontDataFactory}
    rangeChunkSize指定每個范圍請求獲取的最大字節數NumberDEFAULT_RANGE_CHUNK_SIZE
    range允許使用自定義范圍PDFDataRangeTransport-
    pdfBug啟用用于調試 PDF.js 的特殊鉤子(請參閱web / debugger.js)Objectfalse
    password用于解密受密碼保護的 PDFString-
    ownerDocument指定一個顯式的文檔上下文來創建元素并將資源(例如字體)加載到其中HTMLDocument-
    maxImageSize總像素中允許的最大圖像大小,即寬 * 高。不會呈現高于此值的圖像。使用 -1 表示沒有限制,這也是默認值Number-
    lengthPDF 文件長度。它用于進度報告和范圍請求操作Number-
    isEvalSupported確定我們是否可以將字符串評估為 JavaScript。主要用于提高字體渲染的性能,以及解析 PDF 函數時Booleantrue
    initialData帶有第一部分或全部 pdf 數據的類型化數組。由擴展使用,因為在切換到范圍請求之前已經加載了一些數據。TypedArray-
    httpHeaders基本身份驗證請求頭Object-
    fontExtraProperties從工作線程導出解析的字體數據時,包括在渲染 PDF 文檔期間未使用的其他屬性,這對于調試目的(和向后兼容性)可能很有用,但請注意,它會導致內存使用量增加Booleanfalse
    enableXfa渲染 Xfa 表格Booleanfalse
    docBaseUrl文檔的基本 URL,在嘗試恢復注釋和大綱項的有效絕對 URL 時使用,(錯誤地)僅指定了相對 URLstring-
    disableStream禁用 PDF 文件數據的流式傳輸。默認情況下,PDF.js 嘗試分塊加載 PDF 文件Objectfalse
    disableRange禁用 PDF 文件的范圍請求加載。啟用后,如果服務器支持部分內容請求,則 PDF 將分塊獲取Booleanfalse
    disableFontFace默認情況下,字體會轉換為 OpenType 字體并通過字體加載 API 或@font-face 規則加載。如果禁用,字體將使用內置字體渲染器渲染,該渲染器使用原始路徑命令構建字形。Boolean-
    disableAutoFetch禁用預取 PDF 文件數據。啟用范圍請求后,即使不需要顯示當前頁面,PDF.js 也會自動繼續獲取更多數據Objectfalse
    data二進制 PDF 數據。使用類型化數組 (Uint8Array) 來提高內存使用率。如果 PDF 數據是 BASE64 編碼的,請先使用 atob() 將其轉換為二進制字符串。TypedArray、Array、String-
    cMapUrl預定義 Adobe CMap 所在的 URL。包括尾部斜杠String-
    CMapReaderFactory自定義工廠對于沒有 Fetch API 或 XMLHttpRequest 支持的環境很有用,例如 Node.jsObject{DOMCMapReaderFactory}
    cMapPacked指定 Adobe CMap 是否是二進制打包Boolean-

    最后,發現可能是這個庫的問題還是什么,目前不太清楚,他總是從13M以上才開始快速渲染,而我們當時的文件大小差不多也是13M,所以采用了分片下載后,還是存在一段比較長的白屏時間,所以最后還是選用了將pdf轉成圖片再顯示的形式。

    感謝各位的閱讀,以上就是“文件預覽PDF.js使用技巧有哪些”的內容了,經過本文的學習后,相信大家對文件預覽PDF.js使用技巧有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    泗洪县| 乌苏市| 靖州| 昔阳县| 安溪县| 乐清市| 中超| 台南市| 普格县| 永新县| 怀柔区| 香格里拉县| 阳高县| 阳新县| 鄂温| 新沂市| 新田县| 大荔县| 竹溪县| 呈贡县| 凉山| 宁波市| 兰西县| 贵溪市| 衡南县| 达州市| 那坡县| 会东县| 广东省| 山东省| 涡阳县| 西青区| 临夏县| 铜川市| 济阳县| 兴海县| 桑植县| 苗栗市| 荆州市| 麻栗坡县| 许昌县|