知识库

技术文档与知识分享

PDF.js预览功能开发知识库

文章内容

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 条评论

换肤