一些情况下后端返回的数据流是base64编码,无法用过viewer.html?file=的方式绘制在线预览pdf页面,所以需要自己动手写pdfjs的解析方法

一、官网:http://mozilla.github.io/pdf.js/

下载PDF.js目录如下
在这里插入图片描述
将文件存放在项目文件夹’src/pdfjs’

二、使用方法

1.创建previewPdf.js文件,用来解析base64编码文件流

// src/previewPdf.js
import pdfjsLib from '@/pdfjs/build/pdf.js'

let loadingTask = null;
let scale = 0.85

//检查操作系统
function detectOS() {
    var sPlatform = navigator.platform;
    var isLinux = (String(sPlatform).indexOf("Linux") > -1);
    if (isLinux) return "Linux";
}

function renderPdfJs(pdfData){
	let userAgent = navigator.userAgent;
    if (userAgent && userAgent.indexOf("Firefox") > -1) { 
        pdfjsLib.GlobalWorkerOptions.workerSrc = '@/pdfjs/build/pdf.worker.js' //火狐系统配置
    }
    var OsName = detectOS(); //获取操作系统
    if (OsName == "Linux") { //操作系统是linux时,需要载入字体
        var CMAP_URL = '../../pdfjs/cmaps/'; //根据项目中previewPdf.js文件存放地址,写入自己的字体文件夹
        loadingTask = pdfjsLib.getDocument({
            data: pdfData,
            cMapUrl: CMAP_URL,
            cMapPacked: true
        });

    } else {
        loadingTask = pdfjsLib.getDocument({ data: pdfData });
    }

	loadingTask.promise.then(function (pdf) {
        var container = document.getElementById('pdfjsShow');
        //清空子节点
        $(container).empty();
        showAllPdf(pdf, 1, pdf.numPages, container)
    }, function (reason) {
        console.error(reason);
    });
}

/**
 * 解析文件,写入canvas,通过promise链式调用,防止在linux系统中,大文件pdf在线渲染时,存在页数错乱问题
 * @param {loadingTask.promise回调参数} pdf 
 * @param {pdf页数} num 
 * @param {总页数} pageTotalNum 
 * @param {存放pdf元素} container 
 * @returns 
 */
function showAllPdf(pdf, num, pageTotalNum, container){
    pdf.getPage(num).then(function(page) {
        num++;
        let renderContext = getCanvasContent(page, container)
        return page.render(renderContext);
    }).then(function() {
        if(num <= pageTotalNum){
            return showAllPdf(pdf, num, pageTotalNum, container)
        }
    })
}

/**
 * 解析文件,写入canvas
 * @param {pdf页} page 
 * @param {存放pdf元素} container 
 * @returns 
 */
function getCanvasContent(page, container){
    var curScale = scale;
    var viewport = page.getViewport(curScale);
    var canvas = document.createElement('canvas');
    canvas.setAttribute('id', 'pageCanvas-' + (page.pageIndex + 1));
    canvas.setAttribute('style', 'margin: 0 auto;display:block;');
    container.appendChild(canvas);
    var context = canvas.getContext('2d');
    var CSS_UNITS = 96.0 / 72.0;
    canvas.height = Math.floor(viewport.height * CSS_UNITS);
    canvas.width = Math.floor(viewport.width * CSS_UNITS);
    var renderContext = {
        transform: [CSS_UNITS, 0, 0, CSS_UNITS, 0, 0],
        canvasContext: context,
        viewport: viewport
    };
    return renderContext
}

export default {
    renderPdfJs
}

2.创建showPdf.vue文件,展示pdf

<template>
    <div class="preview-pdf">
        <div id="modalBg">
            <!-- <canvas id="modalBg-canvas" width="900" height="200" style="margin: 0 auto; padding: 0; display: block">
                抱歉,你的浏览器並不支持&lt;canvas&gt;元素
            </canvas> -->
        </div>
        <div class="down-footer">
            <div class="page-num">&nbsp;&nbsp;&nbsp;<span id="page_totalNum">{{currentPageNum}}</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span id="index">{{voucherList.length}}</span>&nbsp;&nbsp;&nbsp;</div>
            <div class="btn-list">
                <a-button class="btn" type="button" @click="zoomIn">放大</a-button>
                <a-button class="btn" type="button" @click="zoomOut">缩小</a-button>
                <a-button class="btn" type="button" @click="zoomToFit">自适应</a-button>
                <a-button class="btn" type="button" @click="printCurrentVoucher">打印当前</a-button>
                <a-button class="btn" type="button" @click="printAllVoucher">打印全部</a-button>
                <a-button class="btn" type="button" @click="reLoad">重新加载</a-button>
            </div>
            <div id="downLoad" style="display: none;"></div>
        </div>
    </div>
</template>
<script>
import previewPdf from './previewPdf.js'
export default {
    data() {
        return {
        	pdfData: atob('JVBERi0xLjQKJeLjz9MKNCAwIG9iago8PC9GaWx0ZX...'); //根据自身base64编码
        }
    },
    mounted() {
        previewPdf.renderPage(this.pdfData)
    },
    methods: {
    	zoomIn(){}, //放大/缩小/自适应这边就不详细描述了,具体思路,就是操作previewPdf.js中的scale参数,可根据自己需求,进行修改previewPdf.js文件
    	zoomOut(){},
    	zoomToFit(){},
        print(imgHtml){
            $(`<div style="width: 100%; height: 100%; text-align: center;">
                ${imgHtml}
            </div>`).print()
        },
        printCurrentVoucher() {
            let imgHtml = ''
            document.getElementsByTagName('canvas').forEach(element => {
                let imgSrc = element.toDataURL()
                imgHtml += `<img style="width:100%" src="${imgSrc}"/>`
            });
            this.print(imgHtml)
        },
        async printAllVoucher() {}, //思路 loadingTask.promise 获取解析得倒canvas,直接使用canvas.toDataURL转成img的src
    	reLoad(){
    		location.reload()
    	}
    }
}
</script>
<style lang="less" scoped>
.preview-pdf {
    height: 100%;
    #modalBg{
        height: 100%;
        width: 100%;
        overflow: auto;
        margin: 0 auto;
        padding: 0; 
        display: block;
        background: #ccc;
        canvas{
            height: 100%;
        }
    }
}
</style>

项目demo地址:pdf预览github地址

Logo

前往低代码交流专区

更多推荐