PDF文件在页面中使用canvas渲染,如果接口再配合文件流输出,就可以防止别人复制文件、下载你的PDF文件。
下图就是PDF文件采用文件流输出,也可以把文件流加密,前端去解密(具体就在下面代码的 arraybuffer 中处理)
接下来我们看看具体实现步骤:
1、安装依赖
// 注意:此版本是@2.0.943,不然你运行时候一直报错:
// error in ./node_modules/pdfjs-dist/build/pdf.js
npm install pdfjs-dist@2.0.943
2、vue页面中的写法:
<template>
<div class="pdf-container">
<canvas v-for="page in pages" :id="'canvas' + page" :key="page"></canvas>
</div>
</template>
<script>
import PDF from "pdfjs-dist";
import { Loading } from "element-ui";
import * as api from "@/api/yourapi";
PDF.disableWorker = true;
export default {
data() {
return {
pdfDoc: null,
pages: 0,
};
},
async mounted() {
await this.fetchPDFData(id);
},
methods: {
/*
* 加载PDF文件
* url:后台提供的pdf地址或者项目中public/pdf文件(test.pdf)
* 在需要的位置调用 this.loadFile(url)
* */
async loadFile(url) {
await PDF.getDocument(url).then((pdf) => {
this.pdfDoc = pdf;
this.pages = this.pdfDoc.numPages;
this.$nextTick(() => {
this.renderPage(1);
});
});
},
/*
* 渲染PDF文件
*/
renderPage(num) {
this.pdfDoc.getPage(num).then((page) => {
let canvas = document.getElementById("canvas" + num);
let ctx = canvas.getContext("2d");
let dpr = window.devicePixelRatio || 1; // 设备像素比
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1; // 浏览器在渲染canvas之前会用几个像素来来存储画布信息,类似img
let ratio = dpr / bsr;
let viewport = page.getViewport(1.5);
canvas.width = viewport.width * ratio; // 画布大小,默认值是width:300px,height:150px
canvas.height = viewport.height * ratio;
// canvas.style.width = viewport.width + "px"; // 画布的框架大小
// canvas.style.height = viewport.height + "px";
let renderContext = {
canvasContext: ctx,
viewport: viewport,
};
page.render(renderContext);
if (this.pages > num) {
this.renderPage(num + 1);
}
});
},
/**
* 获取pdf文件流
* 默认传 coursewareId,
* 如果有自己的参数,coursewareId 传空
*/
async fetchPDFData(id) {
const loading = Loading.service({
fullscreen: true,
lock: true,
text: "pdf文档加载中,请稍后...",
background: "rgba(0,0,0,0.75)",
});
let param = { youid : id };
//showYourPdf是你接口的名称
await api.showYourPdf(param).then(async (res) => {
setTimeout(() => {
loading.close();
}, 1000);
let arraybuffer = new Uint8Array(res.data);
this.loadFile(arraybuffer);
});
},
},
};
</script>
<style lang="scss" scoped>
.pdf-container {
canvas {
margin: 0 auto;
}
}
</style>