天天看点

Vue项目中使用pdf.js预览pdf文件流Vue项目中使用canvas和pdf.js预览pdf文件流

Vue项目中使用canvas和pdf.js预览pdf文件流

网上目前的解决方案大多是在将pdf.js放在static文件内,这样j6angjin的后果就是打包文件变得非常大(我的项目由800k变大到将近5m),后来发现了pdf.js的node包pdf_dist这个给我们提供了一个新的方向,使用npm安装避免了打包文件过大的问题。

代码实现

<template>
  <div>
    <canvas v-for="page in pages" :id="'the-canvas'+page" :key="page"></canvas>
  </div>
</template>
<script>
import service from '@api/main'
import PDF from "pdfjs-dist";
import {
    staticUrl
  } from '@utils/config'
export default {
	data() {
		return {
			PDFData:null,
			pages: null
		};
	},
	mounted() {
		let url=this.$route.query.url
		//ajax请求获取文件流,可根据自己需要修改
		service.getPdfUrl(url).then(
			data=>{
			this.PDFData = data
			let pdfurl=this.getObjectURL(this.PDFData)
			this._loadFile(pdfurl); 	
			}
		)
		
	},
	components: {},
	methods: {
		//根据文件流获取url地址(使用blob)
		getObjectURL(data) {
			let blob = new Blob([data], {type: 'application/vnd.ms-excel;charset=utf-8'});//文件流转为blob
			let url = window.URL.createObjectURL(blob); //创建下载的链接
			return url
		},
		//加载PDF
		_loadFile(url) {
			PDF.getDocument(url).then(pdf => {
				this.pdfDoc = pdf;
				this.pages = this.pdfDoc.numPages;
				this.$nextTick(() => {
				this._renderPage(1);//渲染第一页PDF
				});
			});
		},
		//渲染PDF
		_renderPage(num) {
			this.pdfDoc.getPage(num).then(page => {
				let canvas = document.getElementById("the-canvas" + num); //canvas画布作为PDF展示容器~~
				let ctx = canvas.getContext("2d");
				let dpr = window.devicePixelRatio || 1;
				let bsr =
					ctx.webkitBackingStorePixelRatio ||
					ctx.mozBackingStorePixelRatio ||
					ctx.msBackingStorePixelRatio ||
					ctx.oBackingStorePixelRatio ||
					ctx.backingStorePixelRatio ||
					1;
				let ratio = dpr / bsr;
				let viewport = page.getViewport(
					screen.availWidth / page.getViewport(1).width
				);
				canvas.width = viewport.width * ratio;
				canvas.height = viewport.height * ratio;
				canvas.style.width = viewport.width + "px";
				canvas.style.height = viewport.height + "px";
				ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
				let renderContext = {
					canvasContext: ctx,
					viewport: viewport
				};
				page.render(renderContext);
				if (this.pages > num) {
					this._renderPage(num + 1);//如pdf有多页,则多次渲染
				}
			});
		}
		
	}
};
</script>
           

注意事项

vue中引入pdfjs依赖

npm install pdfjs-dist --save
           

获取文件流的请求需要添加responseType: ‘blob’,

const Axios = axios.create({
	baseURL: baseURL,
	responseType: 'blob',
	headers: {
		'Content-Type': 'application/x-www-form-urlencoded;charse