在PDF.js中改造viewer.html
實現PDF動態加載,需結合參數傳遞、文件流處理及跨域配置等技術。以下是綜合多個技術方案的核心實現步驟:
?一、基礎參數傳遞法?
1. ?URL參數動態加載?
通過修改viewer.html
的URL參數傳遞PDF路徑,適用于靜態文件或服務端直鏈:
-
?實現方式?:在
viewer.html
的URL后添加?file=
參數,例如:html 運行 復制 <iframe src="viewer.html?file=http://example.com/doc.pdf"></iframe>
-
?關鍵代碼調整?:在
viewer.js
中注釋或修改跨域檢查代碼,并在webViewerInitialized
事件中解析URL參數:javascript 復制 const urlParams = new URLSearchParams(window.location.search); const pdfUrl = urlParams.get('file'); PDFViewerApplication.open(pdfUrl);
?二、文件流動態加載?
2. ?通過Ajax獲取二進制流?
適用于后端返回PDF字節流而非靜態鏈接的場景:
-
?前端改造?:在
viewer.html
中添加Ajax請求邏輯(需在引入viewer.js
前執行):javascript 復制 fetch('/api/get-pdf-stream').then(response => response.arrayBuffer()).then(data => {const uint8Array = new Uint8Array(data);PDFViewerApplication.open(uint8Array);});
-
?后端要求?:響應頭需設置
Content-Type: application/pdf
,并處理CORS。
3. ?Base64數據加載?
若需處理Base64編碼的PDF數據:
javascript
復制
const base64ToUint8Array = (base64) => {const binaryString = atob(base64.split(',')[1]);const len = binaryString.length;const bytes = new Uint8Array(len);for (let i = 0; i < len; i++) {bytes[i] = binaryString.charCodeAt(i);}return bytes;
};
PDFViewerApplication.open(base64ToUint8Array(base64Data));
?三、跨框架通信方案?
4. ?使用postMessage傳遞數據?
當viewer.html
嵌入iframe時,通過父子頁面通信傳遞PDF數據:
-
?父頁面發送數據?:
javascript 復制 const iframe = document.getElementById('pdfFrame'); iframe.contentWindow.postMessage({action: 'loadPdf',data: pdfBytes // 可以是URL、Uint8Array或Base64 }, '*');
-
?子頁面(viewer.html)監聽?:
javascript 復制 window.addEventListener('message', (event) => {if (event.data.action === 'loadPdf') {PDFViewerApplication.open(event.data.data);} });
此方法可繞過
sessionStorage
的5MB限制。
?四、深度定制viewer.js?
5. ?核心代碼修改?
-
?禁用默認文件加載?:刪除或注釋
viewer.js
中DEFAULT_URL
的定義。 -
?事件觸發時機?:在
webViewerLoaded
事件中動態注入加載邏輯,確保PDF.js初始化完成后再操作:javascript 復制 PDFViewerApplication.initializedPromise.then(() => {// 動態加載代碼 });
?五、跨域與安全處理?
6. ?跨域配置?
-
?服務端?:設置響應頭
Access-Control-Allow-Origin: *
。 -
?PDF.js改造?:在
viewer.js
中注釋以下代碼段以禁用跨域檢查:javascript 復制 if (origin !== viewerOrigin && protocol !== 'blob:') {throw new Error('跨域禁止'); }
7. ?電子簽章兼容性?
在pdf.worker.js
中注釋簽名驗證代碼段:
javascript
復制
// 注釋以下三行(約第2000行)
if (this.fieldType === 'Sig') {this._setFlags(AnnotationFlag.HIDDEN);
}
?六、性能優化建議?
-
?按需渲染?:參考PDF.js的分頁渲染機制,僅預加載可視區域頁面。
-
?內存管理?:調用
PDFViewerApplication.close()
釋放已卸載文檔內存。 -
?錯誤處理?:監聽
documentloaderror
事件實現容錯:javascript 復制 PDFViewerApplication.eventBus.on('documentloaderror', (err) => {console.error('加載失敗:', err); });
?擴展場景示例?
動態加載加密PDF
javascript
復制
PDFViewerApplication.open({url: 'encrypted.pdf',password: 'user123'
}).catch(reason => {// 彈出密碼輸入框PDFViewerApplication.pdfViewer.passwordPrompt();
});
通過上述方案,可實現從URL、二進制流、Base64、跨框架通信等多渠道動態加載PDF,同時解決電子簽章、跨域限制等疑難問題。具體實現需根據項目架構選擇合適的技術組合。