文章内容
PDF.js预览功能开发指南
本文档提供PDF.js预览功能的完整开发指南,包括技术选型、核心API、常见问题和最佳实践。
一、技术选型
1. PDF.js版本选择
| 版本 | 稳定性 | 推荐指数 | 说明 |
||--|-||
| 3.11.174 | 稳定 | 推荐 | 生产环境首选 |
| 4.0.x | 一般 | 谨慎 | 可能存在兼容性问题 |
| 2.x | 稳定 | 可用 | 旧版本,功能完整 |
推荐使用3.11.174版本,稳定性最好。
2. 引入方式
CDN方式(推荐)
html
本地部署方式
下载PDF.js库文件到项目目录,然后引入。
html
二、核心API
1. 全局配置
设置Worker路径是必须的配置。
javascript
pdfjsLib.GlobalWorkerOptions.workerSrc =
'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
2. 加载PDF文档
基础加载
javascript
const loadingTask = pdfjsLib.getDocument('document.pdf');
loadingTask.promise.then(function(pdf) {
console.log('PDF加载成功,页数:', pdf.numPages);
});
带配置的加载
javascript
const loadingTask = pdfjsLib.getDocument({
url: 'document.pdf',
cMapUrl: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/cmaps/',
cMapPacked: true
});
3. 渲染页面
获取页面
javascript
pdf.getPage(1).then(function(page) {
console.log('页面获取成功');
});
渲染到Canvas
javascript
pdf.getPage(1).then(function(page) {
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.getElementById('pdfCanvas');
canvas.height = viewport.height;
canvas.width = viewport.width;
const context = canvas.getContext('2d');
const renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
4. 渲染所有页面
javascript
async function renderAllPages(pdf, container) {
container.innerHTML = '';
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const viewport = page.getViewport({ scale: 1.0 });
const scale = container.clientWidth / viewport.width;
const scaledViewport = page.getViewport({ scale: scale });
const canvas = document.createElement('canvas');
canvas.height = scaledViewport.height;
canvas.width = scaledViewport.width;
canvas.style.display = 'block';
canvas.style.margin = '0 auto 20px';
await page.render({
canvasContext: canvas.getContext('2d'),
viewport: scaledViewport
}).promise;
container.appendChild(canvas);
}
}
三、常见问题
问题1:PDF.js未定义
现象
控制台报错:pdfjsLib is not defined
原因
PDF.js库未正确加载
解决方案
检查PDF.js库是否正确引入,添加加载检查。
javascript
if (typeof pdfjsLib === 'undefined') {
console.error('PDF.js未加载');
return;
}
问题2:Worker路径错误
现象
控制台显示"Setting up fake worker"警告
原因
Worker路径配置错误或未配置
解决方案
正确配置Worker路径。
javascript
pdfjsLib.GlobalWorkerOptions.workerSrc =
'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
问题3:中文字符显示异常
现象
PDF中的中文字符显示为方块或乱码
原因
未配置字符映射(cMap)
解决方案
加载PDF时配置cMap。
javascript
pdfjsLib.getDocument({
url: 'document.pdf',
cMapUrl: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/cmaps/',
cMapPacked: true
});
问题4:跨域问题
现象
某些PDF无法加载,控制台报跨域错误
原因
PDF文件所在域名没有配置CORS
解决方案
方案一:配置服务器CORS头
nginx
location ~ \.pdf$ {
add_header Access-Control-Allow-Origin ;
}
方案二:使用同域文件
将PDF文件放在同域下,避免跨域。
问题5:内存占用过高
现象
加载大型PDF时浏览器卡顿或崩溃
原因
一次性渲染所有页面占用大量内存
解决方案
实现分页加载,只渲染可见页面。
javascript
let currentPage = 1;
const pageSize = 5;
function renderPageRange(pdf, start, end) {
for (let i = start; i <= end; i++) {
if (i > pdf.numPages) break;
renderPage(pdf, i);
}
}
function loadMore() {
const start = currentPage;
const end = currentPage + pageSize - 1;
renderPageRange(pdf, start, end);
currentPage += pageSize;
}
四、完整示例
基础预览组件
html
带工具栏的预览组件
html
五、最佳实践
1. 性能优化
分页加载
对于大型PDF,实现分页加载,只渲染可见页面。
延迟渲染
使用Intersection Observer API实现懒加载。
javascript
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
renderPage(entry.target.dataset.pageNum);
}
});
});
缓存机制
缓存已渲染的页面,避免重复渲染。
2. 错误处理
全局错误捕获
javascript
window.addEventListener('error', function(e) {
console.error('PDF加载错误:', e.message);
});
Promise错误处理
javascript
pdfjsLib.getDocument(url).promise
.then(function(pdf) {
// 成功处理
})
.catch(function(error) {
console.error('PDF加载失败:', error);
showError('PDF加载失败,请重试');
});
3. 移动端适配
响应式缩放
javascript
function getScale(containerWidth, pageWidth) {
return containerWidth / pageWidth;
}
window.addEventListener('resize', function() {
renderAllPages();
});
触摸手势
支持双指缩放和滑动翻页。
4. 安全性
文件类型验证
python
ALLOWED_EXTENSIONS = {'pdf'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
文件大小限制
python
MAX_CONTENT_LENGTH = 16 1024 1024 16MB
路径安全检查
python
import os
def is_safe_path(base_dir, filename):
filepath = os.path.realpath(os.path.join(base_dir, filename))
return filepath.startswith(os.path.realpath(base_dir))
六、API参考
pdfjsLib.getDocument(config)
加载PDF文档。
参数
- url: PDF文件URL(字符串)
- data: PDF数据(TypedArray)
- cMapUrl: 字符映射URL
- cMapPacked: 是否使用压缩的cMap
返回值
返回Promise,resolve时传递PDFDocumentProxy对象。
PDFDocumentProxy
属性
- numPages: PDF页数
方法
- getPage(pageNumber): 获取指定页面,返回Promise
PDFPageProxy
方法
- getViewport(config): 获取视口配置
- render(config): 渲染页面到Canvas
七、调试技巧
1. 开启调试模式
javascript
pdfjsLib.GlobalWorkerOptions.workerSrc =
'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.js';
使用未压缩版本便于调试。
2. 查看加载状态
javascript
loadingTask.onProgress = function(progress) {
console.log('加载进度:', progress.loaded / progress.total 100 + '%');
};
3. 检查渲染状态
javascript
page.render(renderContext).promise.then(function() {
console.log('页面渲染成功');
}).catch(function(error) {
console.error('页面渲染失败:', error);
});
八、参考资源
- [PDF.js官方文档](https://mozilla.github.io/pdf.js/)
- [PDF.js GitHub仓库](https://github.com/mozilla/pdf.js)
- [PDF.js示例](https://mozilla.github.io/pdf.js/examples/)
- [MDN Canvas文档](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API)
更新日期: 2026-03-19
版本: 1.0
评论列表
0 条评论