項(xiàng)目中使用的是vue框架
1、在入口文件中添加 <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
2、代碼如下
<template>
<div class="components-preview-pdf-page">
<div v-if="src" class="pdf_list">
<div class="show-pdf-info">
<span>{{currentPage}} / {{totalPages}}</span>
<van-button @click="changePage('last')" :disabled="currentPage === 1">上一頁</van-button>
<van-button @click="changePage('next')" v-if="totalPages > 1" :disabled="currentPage === totalPages">下一頁</van-button>
</div>
<canvas id="the-canvas"></canvas>
</div>
<div v-else>
<default-page showText="暫無數(shù)據(jù)"></default-page>
</div>
</div>
</template>
<script>
import defaultPage from '@/components/app/common/defaultPage.vue'
import {mapActions, mapMutations} from "vuex";
export default {
components: { defaultPage},
data() {
return {
currentPage: 1,//當(dāng)前頁
totalPages: 0,//總頁數(shù)
}
},
watch: {},
props: {
src: String
},
computed: {},
mounted() {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js'
if (this.src) {
this.loadPdfPage()
}
},
methods: {
...mapMutations(['setLoading']),
...mapActions([
]),
//因?yàn)椴寮看沃徽故疽豁?,所以要手?dòng)控制頁數(shù)
changePage(val) {
if (val === 'last' && this.currentPage > 1) {
this.currentPage--
}
else if (val === 'next' && this.currentPage < this.totalPages) {
this.currentPage++
}
this.loadPdfPage()
},
loadPdfPage(){
this.setLoading(true)
pdfjsLib.getDocument(this.src).promise.then( (pdf) => {
this.totalPages = pdf.numPages
pdf.getPage(this.currentPage).then( (page) => {
var scale = 1.5
var viewport = page.getViewport({ scale: scale });
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
}
this.setLoading(false)
page.render(renderContext);
})
})
},
}
}
</script>
<style scoped lang="less">
.components-preview-pdf-page {
height: 100vh;
.pdf_list {
//height: 100%;
//overflow: scroll;
font-size: 0.28rem;
.show-pdf-info{
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0.1rem 0.32rem;
.van-button{
margin-left: 0.12rem;
height: 0.56rem;
padding: 0.08rem 0.12rem;
font-size: 0.28rem;
}
}
#the-canvas{
width: 100%;
//height: 100%;
overflow-y: scroll;
}
}
}
</style>
3、組件引用
<template>
<div class="app-yk-user-examination-report-detail-page">
<header-top title="體檢報(bào)告" showReturn="black"></header-top>
<div class="date-time" >體檢時(shí)間:{{examinationDate}}</div>
<div class="pdf_list">
<preview-pdf v-if="fileStream" :src="fileStream"></preview-pdf>
</div>
</div>
</template>
<script>
import headerTop from '@/components/app/common/header/top.vue'
import previewPdf from '@/components/previewPdf.vue'
import {mapActions, mapMutations} from 'vuex'
export default {
name: 'appYingkangLifeTimeUserExaminationReport',
components: {headerTop, previewPdf},
data() {
return {
fileStream: '',
id: this.$route.query.id || '',
examinationDate: this.$route.query.examinationDate || ''
}
},
watch: {},
props: {},
computed: {},
mounted() {
this.loadPdf()
},
methods: {
...mapMutations(['setLoading']),
...mapActions([
]),
loadPdf(){
// 移動(dòng)端預(yù)覽需要將文件流轉(zhuǎn)化為arrayBuffer
this.setLoading(true)
this.$http.get('接口名字?tjbh=' + this.id, {
responseType: 'arraybuffer',
}).then(res => {
this.fileStream = res.request.response
this.setLoading(false)
}).catch(error => {
this.setLoading(false)
}).finally( msg => {
this.setLoading(false)
})
}
}
}
</script>
<style scoped lang="less">
.app-yk-user-examination-report-detail-page {
height: 100vh;
.date-time{
text-align: right;
padding: 0.2rem 0.32rem;
font-size: 0.28rem;
}
.pdf_list {
height: calc(100% - 1.68rem);
//overflow: scroll;
font-size: 0.28rem;
.components-preview-pdf-page{
height: 100%!important;
}
.show-pdf-info {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0.1rem 0.32rem;
.van-button {
margin-left: 0.12rem;
height: 0.56rem;
padding: 0.08rem 0.12rem;
font-size: 0.28rem;
}
}
#the-canvas {
width: 100%;
//height: 100%;
overflow-y: scroll;
}
}
}
</style>
總結(jié):移動(dòng)端預(yù)覽需要將文件流轉(zhuǎn)化為arrayBuffer,否則使用插件會(huì)報(bào)錯(cuò)。通過 Axios 的 get 方法請(qǐng)求一個(gè)資源,并將 responseType 設(shè)置為 arraybuffer,這樣 Axios 會(huì)將響應(yīng)體作為 arrayBuffer 返回。然后在 .then 回調(diào)中可以對(duì)這個(gè) arrayBuffer 進(jìn)行進(jìn)一步的處理。
組件升級(jí)優(yōu)化:預(yù)覽pdf在組件內(nèi)部處理文件流還是預(yù)覽在線pdf
<template>
<div class="components-preview-pdf-page">
<div v-if="src" class="pdf_list" ref="pdfBox">
</div>
<div v-else>
<default-page showText="暫無數(shù)據(jù)"></default-page>
</div>
</div>
</template>
<script>
import defaultPage from '@/components/app/common/defaultPage.vue'
import {mapActions, mapMutations} from "vuex";
export default {
components: { defaultPage},
data() {
return {
}
},
watch: {},
props: {
src: String,//在線pdf路徑,或者如果跟后端確認(rèn)必須走接口獲取文件流格式預(yù)覽的話,type是stream,這個(gè)src就是接口名字
type: {
type: String,
default: 'online' //online是線上的,stream是文件流
}
},
computed: {},
mounted() {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js'
if (this.src) {
this.loadPdf(this.src)
}
},
methods: {
...mapMutations(['setLoading']),
...mapActions([
]),
// 獲取文件流 arraybuffer格式的
getFileStream(url) {
return new Promise((resolve, reject) => {
this.$http.get(url, {
responseType: 'arraybuffer',
}).then(res => {
resolve(res.request.response)
}).catch(error => {
resolve(error)
}).finally( msg => {
resolve(msg)
})
})
},
//加載pdf
async loadPdf(url) {
this.setLoading(true)
try {
let loadingTask = ''
if (this.type === 'online') loadingTask = pdfjsLib.getDocument(url);
else {
// 如果是文件流格式的話需要獲取一下arraybuffer
let data = await this.getFileStream(url)
loadingTask = pdfjsLib.getDocument({ data });
}
const pdfDocument = await loadingTask.promise;
for (let pageNumber = 1; pageNumber <= pdfDocument.numPages; pageNumber++) {
const page = await pdfDocument.getPage(pageNumber);
var scale = 1.5
var viewport = page.getViewport({ scale: scale });
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = viewport.width;
canvas.height = viewport.height;
canvas.style = 'width: 100%'
this.$refs.pdfBox.appendChild(canvas);
const renderTask = page.render({
canvasContext: context,
viewport: viewport
});
await renderTask.promise;
this.setLoading(false)
}
} catch (error) {
console.error('Error loading PDF:', error);
}
},
}
}
</script>
<style scoped lang="less">
.components-preview-pdf-page {
height: 100vh;
.pdf_list {
//height: 100%;
//overflow: scroll;
font-size: 0.28rem;
>.sdd{
width: 100%!important;
height: auto;
}
.show-pdf-info{
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0.1rem 0.32rem;
.van-button{
margin-left: 0.12rem;
height: 0.56rem;
padding: 0.08rem 0.12rem;
font-size: 0.28rem;
}
}
#the-canvas{
width: 100%;
//height: 100%;
overflow-y: scroll;
}
}
}
</style>
組件使用的時(shí)候可以表明是在線預(yù)覽pdf還是走接口形式

image.png