需求:在手机端实现pdf的文件与下载,主要是zlb_app中
实现过程:在研究了vue-pdf、pdfjs、pdfh5之后,选择了vue-pdf-signature,vue-pdf的升级版本
在vue-pdf和pdfjs中引入cmaps字体文件后,依旧显示不完整
技术 | 安卓 | iOS | 选择 |
---|---|---|---|
vue-pdf | 部分文字丢失,显示不完整 | 部分文字丢失,显示不完整 | ❌ |
pdf-js | 文字乱码 | 文字乱码 | ❌ |
vue-pdf-signature | 显示完整 | 显示完整 | ✔️ |
表1:浙里办app预览方案对比
代码实现:pdf的预览
需要引入字体文件import CMapReaderFactory from ‘vue-pdf-signature/src/CMapReaderFactory’,在pdf创建时设置pdf.createLoadingTask
<!-- 页面引入vue-pdf-signature后,使用pdf组件 -->
<div>
<p v-show="!show" style="position:absolute;top:0;left:0;text-align:center;width:100%;padding-top:0.2rem;">PDF加载中,请耐心等待...</p>
<pdf
v-show="show"
v-for="i in numPages"
:key="i"
:src="src"
:page="i"
:rotate="rotate"
class="pdf"
:style="style"
></pdf>
</div>
import pdf from 'vue-pdf-signature'
import CMapReaderFactory from 'vue-pdf-signature/src/CMapReaderFactory'
export default {
components: {
pdf
},
name: 'index',
data () {
return {
numPages: "",
src: "",
pdfUrl: "",
show:false,
rotate:0,
style:"width:100%",
widt:100
}
},
methods: {
loadPdf (url) {
console.log('uuurl', url)
this.src = pdf.createLoadingTask({
url: url,
cMapPacked: true,
CMapReaderFactory
})
this.src.promise.then((pdf) => {
this.show = true
this.numPages = pdf.numPages // 这里拿到当前pdf总页数
})
},
},
mounted () {
// 可以是文件流,也可以是可访问地址
this.pdfUrl = `url`
this.loadPdf(this.pdfUrl)
},
}
注意:
pdfUrl可以是后端接口返回的文件流,也可以是文件所在地址,若url中存在符号或中文,在encodeURIComponent之后再赋值,否则后端接收数据不完整
需求:在移动端实现下载功能,适配安卓系统和iOS系统
实现过程:通过a标签的形式,点击后下载。
后端配合:
后端配合,response header中返回
// 强制下载
content-disposition: attachment; filename=04702106000965.pdf
content-type: application/pdf;charset=UTF-8
前端实现,request header设置
//根据文件需求设置,我这里匹配了全部
config.headers.Accept= '*/*'
代码实现:
down()
var e = document.createElement("a");
e.style.display = "none"
//ios系统中,没有xx.pdf不会显示下载按钮,且ios系统使用该方法会先打开预览,再次点击下载才可以
e.href = "".concat(`${this.pdfUrl}`) + '&response-content-type=application/pdf&报告.pdf'
// e.setAttribute("download", "t.pdf")
e.setAttribute("target", "_blank")
document.body.appendChild(e)
console.log(e)
e.click()
document.body.removeChild(e)
}
注意:
e.href的赋值,需要用concat拼接一个空字符串,否则打不开浏览器,拼接
苹果下载:请求中加上xx.pdf才能实现打开预览界面中出现下载按钮
安卓下载:默认打开手机自带浏览器或阅读器,用于下载pdf
总结:下面是vue文件
<template>
<div>
<p v-show="!show" style="position:absolute;top:0;left:0;text-align:center;width:100%;padding-top:0.2rem;">{{text}}</p>
<pdf
v-show="show"
v-for="i in numPages"
:key="i"
:src="src"
:page="i"
class="pdf"
:style="style"
></pdf>
<div v-show="show" @click="down" class="down"></div>
<div v-show="show" @click="add" class="add" ></div>
<div v-show="show" @click="reduce" class="reduce" ></div>
</div>
</template>
<script>
import pdf from 'vue-pdf-signature'
import CMapReaderFactory from 'vue-pdf-signature/src/CMapReaderFactory'
import {aesCode,aesJM,changeTitle, getUserInfo} from '@/utils/index.js'
export default {
components: {
pdf
},
name: 'index',
data () {
return {
numPages: "",
src: "",
pdfUrl: "",
show:false,
rotate:0,
style:"width:100%",
widt:100,
text:'PDF加载中,请耐心等待...'
}
},
methods: {
loadPdf (url) {
this.src = pdf.createLoadingTask({
url: url,
cMapPacked: true,
CMapReaderFactory
})
this.src.promise.then((pdf) => {
this.show = true
this.numPages = pdf.numPages // 这里拿到当前pdf总页数
}).catch(err=>{
console.log(err)
this.text = '暂未查到PDF,请稍后重试...'
})
},
add(){
// 放大
this.widt +=20
this.style = `width:${this.widt}%`
},
reduce(){
// 缩小
this.widt -=20
this.style = `width:${this.widt}%`
},
down () {
var e = document.createElement("a");
e.style.display = "none"
e.href = "".concat(`${this.pdfUrl}`) + '&response-content-type=application/pdf&报告.pdf'
// e.setAttribute("download", "t.pdf")
e.setAttribute("target", "_blank")
document.body.appendChild(e)
console.log(e)
e.click()
document.body.removeChild(e)
},
},
mounted () {
this.pdfUrl = `url`
this.loadPdf(this.pdfUrl)
},
}
</script>
<style scoped>
.down{
width: 0.3rem;
height: 0.3rem;
position: fixed;
right: 0.1rem;
bottom: 1rem;
background-image: url(./download2.png);
background-size: 100% 100%;
background-repeat: no-repeat;
}
.add{
width: 0.3rem;
height: 0.3rem;
position: fixed;
right: 0.1rem;
bottom: 1.8rem;
background-image: url(./add.png);
background-size: 100% 100%;
background-repeat: no-repeat;
}
.reduce{
width: 0.3rem;
height: 0.3rem;
position: fixed;
right: 0.1rem;
bottom: 1.4rem;
background-image: url(./reduce.png);
background-size: 100% 100%;
background-repeat: no-repeat;
}
</style>
该方法在pc端同样适用。