天天看點

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