PDF选取文字进行解析文本

1,985 阅读2分钟

实现该需求,主要分为两部

  1. 利用第三方库将pdf的内容渲染到浏览器中,并且文字可勾选
  2. 利用js方法将勾选的内容获取

我们先了解下PDF在浏览器通常的展示方式:

  1. 在网页中直接打开 PDF 文件进行浏览
  2. 在网页中嵌入 PDF 文件作为页面的一部分

在网页中直接打开 PDF 文件进行浏览:现在主流现代浏览器如 Chrome、Sarafi 基本都内置了支持 PDF 浏览的插件,可以直接打开 PDF 文件,而IE等可能还需要安装插件才能打开 PDF 文件。

在网页中嵌入 PDF 文件作为页面的一部分:可以通过嵌入 iframe 的方式实现,但由于浏览器的同源策略限制,想自定义 PDF 的显示样式让其和页面更和谐,如背景色、默认文字大小,或者禁止打印下载等几乎是不可能的任务。

而PDFjs 则可以统一浏览器中 PDF 的显示(免插件),以及提供更多自定义的功能给web开发者。

PDF.js是什么

PDFjs 由 Mozilla 官方出品,是基于 HTML5 技术构建的用于展示 PDF 的 js 库 ,它可以在现代浏览器中使用且无需安装任何第三方插件。

如何使用PDFjs

方法一

  1. 可以从官方下载地址 中下载Prebuilt版本,将pdf.js、pdf.worker.js进行引入

2. 读取PDF内容,将PDF内容渲染到页面上

let pdfDocument;

let PAGE_HEIGHT;

const DEFAULT_SCALE = 1.5;

let pdfUrl = 'https://www.gjtool.cn/pdfh5/git.pdf'; // 在线地址

pdfjsLib.getDocument(pdfUrl).promise.then(pdf => { 

    pdfDocument = pdf;

    let viewer = document.getElementById('viewer');
    for (let i = 0; i < pdf.numPages; i++) {  // pdf.numPages读取pdf的页数
        let page = createEmptyPage(i+1);  // 根据pdf页面创建多个空的文档div
        viewer.appendChild(page);
    }

    // 先加载第一页
    loadPage(1).then(pdfPage => {
        let viewport = pdfPage.getViewport({scale: DEFAULT_SCALE});
        PAGE_HEIGHT = viewport.height;
        document.body.style.width = `${viewport.width}px`;
    });
})
function createEmptyPage(num) {
    let page = document.createElement('div');
    let canvas = document.createElement('canvas');
    let wrapper = document.createElement('div');
    let textLayer = document.createElement('div');

    page.className = 'page';
    wrapper.className = 'canvasWrapper';
    textLayer.className = 'textLayer';

    page.setAttribute('id', `pageContainer${num}`);
    page.setAttribute('data-loaded', 'false');
    page.setAttribute('data-page-number', num);

    canvas.setAttribute('id', `page${num}`);

    page.appendChild(wrapper);
    page.appendChild(textLayer);
    wrapper.appendChild(canvas);

    return page;
}
// 渲染pdf
function loadPage(pageNum) {
    return pdfDocument.getPage(pageNum).then(pdfPage => {
        let page = document.getElementById(`pageContainer${pageNum}`);
        let canvas = page.querySelector('canvas');
        let wrapper = page.querySelector('.canvasWrapper');
        let container = page.querySelector('.textLayer');
        let canvasContext = canvas.getContext('2d');
        let viewport = pdfPage.getViewport({scale: DEFAULT_SCALE}); // 渲染canvas

        canvas.width = viewport.width * 2;
        canvas.height = viewport.height * 2;
        page.style.width = `${viewport.width}px`;
        page.style.height = `${viewport.height}px`;
        wrapper.style.width = `${viewport.width}px`;
        wrapper.style.height = `${viewport.height}px`;
        container.style.width = `${viewport.width}px`;
        container.style.height = `${viewport.height}px`;

        pdfPage.render({
            canvasContext,
            viewport
        });


        page.setAttribute('data-loaded', 'true');

        return pdfPage;
    });
}
function handleWindowScroll() {
    let visiblePageNum = Math.round(window.scrollY / PAGE_HEIGHT) + 1;
    let visiblePage = document.querySelector(`.page[data-page-number="${visiblePageNum}"][data-loaded="false"]`);
    if (visiblePage) {
        setTimeout(function () {
            loadPage(visiblePageNum);
        });
    }
}

到此PDF内容就已经通过pdfjs渲染到了浏览器里,支持本地PDF文件和线上PDF地址进行预览

将PDF内容在浏览器可勾选

如何将pdf内容的文本解析并以dom的形式展现在对应canvas下事先创建好的div中呢,可以利用pdfjsLib.renderTextLayer进行渲染,具体看如何使用

  1. 首先我们引入web里面的viewer.css文件

2. 然后我们改造loadPage方法

// 渲染pdf
function loadPage(pageNum) {
    return pdfDocument.getPage(pageNum).then(pdfPage => {
        let page = document.getElementById(`pageContainer${pageNum}`);
        let canvas = page.querySelector('canvas');
        let wrapper = page.querySelector('.canvasWrapper');
        let container = page.querySelector('.textLayer');
        let canvasContext = canvas.getContext('2d');
        let viewport = pdfPage.getViewport({scale: DEFAULT_SCALE}); // 渲染canvas

        canvas.width = viewport.width * 2;
        canvas.height = viewport.height * 2;
        page.style.width = `${viewport.width}px`;
        page.style.height = `${viewport.height}px`;
        wrapper.style.width = `${viewport.width}px`;
        wrapper.style.height = `${viewport.height}px`;
        container.style.width = `${viewport.width}px`;
        container.style.height = `${viewport.height}px`;

        pdfPage.render({
            canvasContext,
            viewport
        });

        // 渲染pdf的dom结构
        pdfPage.getTextContent().then(textContent => { 
            pdfjsLib.renderTextLayer({
                textContent: textContent,
                container: container,
                viewport: viewport,
                textDivs: []
            });
        });

        page.setAttribute('data-loaded', 'true');

        return pdfPage;
    });
}

至此PDF文件在浏览器中,文字也就可勾选了

方法二

  1. 利用PDFjs提供的web端模板功能,除了将pdf.js、pdf.worker.js引入外,还需要将viewer.css、viewer.js和viewer.html引入

images为viewer.html引入的字体图标, locale为viewer.html引入的国际化文本

2.1将PDF在新打开页面使用

window.open(viewer.html的路径?file=相对于viewer.html的pdf文件的路径)

2.2 将viewer.html内嵌到网页中使用,使用iframe标签引入

<iframe src="viewer.html的路径?file=相对于viewer.html的pdf文件的路径" id="iframePDF" frameborder="0" style="width:100%;height:100%;min-height:490px"></iframe>

读取勾选内容

利用document.getSelection方法将勾选的内容获取

参考文章:

引入PDFjs

mozilla.github.io/pdf.js/exam…

pdfjs在vue中的使用

解析文字

PDF.js实现个性化PDF渲染(文本复制)

How to render text layer