在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,同时解决电子签章、跨域限制等疑难问题。具体实现需根据项目架构选择合适的技术组合。