• H5移动端文件预览pdf


    H5移动端文件预览pdf

    需求:H5页面嵌入浙政钉,需要文件预览Pdf。

    试用了多个插件,踩了很多坑,如果小伙伴有类似填坑经历,并成功解决,感谢留言指点!!!

    先讲最终方案,兼容ios,安卓,鸿蒙多种系统手机,移动端和pc端的pdf预览方式 — pdf.js + iframe。

    成功案例 pdf.js + iframe

    步骤一: 下载 pdf.js , pdfjs 下载地址:https://pan.baidu.com/s/1Meh_hSlwCPvN6wPKzYNfyQ

    提取码:pdfj
    或官网地址下载: https://mozilla.github.io/pdf.js/

    步骤二: 把下载下来的文件夹,放到项目根目录文件夹下。注意:放在不会被打包压缩的地方,比如 public 或 static 文件夹中,因为后面会用到web 文件中的 view.html 对文件地址进行代理,对于该路径相当于读取静态资源。【注:viewer.html 是pdf 的查看器】
    步骤三:新建一个组件,pdfjs.vue
        
        
        
        
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    步骤四: 使用
     
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    其他踩了很多坑的方案,结果还是不行,时间关系没再仔细研究

    经过下面几个插件的试用,发现ios都能展示,而且用a标签也可以展示,应该是内置了预览组件。安卓和鸿蒙就不行,自带浏览器也都是直接跳下载,谷歌浏览器可以预览。

    1. 简单的前端处理方式:

    url: 文件地址(一般为文件流形式)
    a 标签, 
    
    window.open(url)  //新建窗口打开链接预览
    window.location.href = 文档地址;  //本页面内跳转链接实现预览
    
    iframe 预览:
    
    以上方式,部分浏览器 或 手机app不能直接打开,会自动回退成下载链接,比如鸿蒙,比如IE
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    iframe内嵌常见问题:https://blog.csdn.net/qq_35408366/article/details/128447408

    2. pdfh5 预览(移动端,h5)

    1. npm install pdfh5 , (会报错,需要其他依赖,不能直接用提示的语句直接npm下载,依旧会报错,npm报错:These dependencies were not found:* canvas in ./node_modules/pdfh5/js/pdf.js* dommatrix/dist/d )

    2. npm install canvas@2.8.0 --ignore-scripts

    3. npm install --save dommatrix

    4. npm install --save web-streams-polyfill

    5. 运行就成功了,亲测可行,但是pc端运行打不开 pdf的文件【vue-pdf 和 pdfh5 不可同时引用】,而且需要点两次才能获取到 pdfh5 这个对象。

    6. 引用 pdfh5 和 css【关于css的引入方式,网上也有踩了很多坑的,下面这种是最佳方式,亲测可行】

        import Pdfh5 from 'pdfh5'
        import 'pdfh5/css/pdfh5.css'
    
    • 1
    • 2
    1. 定义容器【id】
        <div id="pdf-content" style="height: 100%;width: 100%"></div>
        
        openPdf(url) {
            // pdfh5实例化时传两个参数:selector选择器,options配置项参数,会返回一个pdfh5实例对象,
            // 可以用来操作pdf,监听相关事件
            this.pdfh5 = new Pdfh5('#pdf-content', {
      	      pdfurl: url || this.preFileUrl,
      	      lazy: false, // 是否懒加载,默认false
      	      renderType: 'canvas', // canvas、svg,默认canvas
      	      maxZoom: 3, // 手势缩放最大倍数,默认3
      	      scrollEnable: true, // 是否允许pdf滚动,默认true
      	      zoomEnable: true,// 是否允许pdf手势缩放,默认true
      	      limit: 0, // 限制pdf加载最大页数,默认0不限制
      	      goto: 1,
      	      // 设置每一页pdf上的水印
      	      // logo: { src: require("@/assets/images/icon27.png"), x: 20, y: 70, width: 60, height: 60 },
            });
            console.log('pdfh5', this.pdfh5)
            // 监听pdf准备开始渲染,此时可以拿到pdf总页数
            this.pdfh5.on('ready', function(totalNum) {
            	console.log('总页数:' + totalNum);
            });
            // 监听pdf加载完成事件,加载失败、渲染成功都会触发
            this.pdfh5.on('complete', (status, msg, time) => {
            	console.log('状态:' + status + ',信息:' + msg + ',耗时:' + time + '毫秒');
            })
        },
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28

    vue2 和 vue3 代码举例: https://blog.csdn.net/u014212540/article/details/129408653

    遇到的问题:

    1. 下载依赖,一直报错,无法正常运行,切换 node 和 npm 版本都无果。解决方式:参考上文1234,按次序下载依赖。
    2. pc端运行打不开 pdf 的文件【vue-pdf 和 pdfh5 冲突,不可同时引用,原因未细究】,而且需要点两次才能获取到 pdfh5 这个对象【未解决】
    3. 安卓直接打不开项目,ios可以正常打开且能预览

    3.vue-pdf 预览

    遇到问题:

    1. vue-pdf 默认只能显示第一页,通过获取总页数遍历解决。
    2. vue-pdf 默认不可手机端两指放大缩小,加 页面放大缩小:
        <template>
        <div class="pdf_wrap">
         <div class="pdf_btn">
           <van-button @click="scaleD()">放大</van-button>
           <van-button @click="scaleX()">缩小</van-button>
           <van-button @click="clock()">顺时针</van-button>
           <van-button @click="counterClock()">逆时针</van-button>
         </div>
         <div class="pdf_list">
           <!-- src:pdf地址,page: 当前显示页 -->
           <pdf
             ref="pdf"
             v-for="i in numPages"
             :key="i"
             :src="src"
             :page="i"
             :rotate="pageRotate"
             style="width: 100%"></pdf>
         </div>
         <van-button class="close" @click="closePdf">
           关闭
         </van-button>
        </div>
        </template> 
        <script>
        import pdf from 'vue-pdf';
        import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js'
        // import pdf from 'vue-pdf/src/vuePdfNoSssNoWorker.vue';
        export default {
        components: {
         pdf,
        },
        props: {
         pdfurl: {
           type: String,
         },
        },
        data() {
         return {
           src: '',
           numPages: undefined,
           scale: 100,
           pageRotate: 0
         }
        },
        mounted() {
         console.log('pdf', pdf)
         this.loadPdf(this.pdfurl)
        },
        methods: {
         loadPdf(url) {
           console.log(url, 'url')
           this.src = pdf.createLoadingTask({
             url,
             // pdf内容文字丢失
             cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/',//引入pdf.js字体
             cMapPacked: true,
             // 动态文字不展示问题
             CMapReaderFactory
           })
           console.log(this.src, 'src')
           this.src.promise.then(pdf => {
             console.log(pdf, 'pdf')
             this.numPages = pdf.numPages // 这里拿到当前pdf总页数
           }).catch(err => {
             console.log('err', err)
           })
           console.log(this.src, 'src11111')
         },
         closePdf() {
           this.$emit('closePdf')
         },
         //放大
         scaleD() {
           this.scale += 20;
           console.log('refs.pdf', this.$refs.pdf)
           if (this.$refs.pdf && this.$refs.pdf.length > 0) {
             this.$refs.pdf.forEach(pdfPage=>{
               pdfPage.$el.style.width = parseInt(this.scale) + '%';
             })
           } else {
             this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%';
           }
         },
         //缩小
         scaleX() {
           if (this.scale === 100) {
             return;
           }
           this.scale += -20;
           if (this.$refs.pdf && this.$refs.pdf.length > 0) {
             this.$refs.pdf.forEach(pdfPage=>{
               pdfPage.$el.style.width = parseInt(this.scale) + '%';
             })
           } else {
             this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%';
           }
         },
         // 顺时针
         clock() {
           this.pageRotate += 90;
         },
         // 逆时针
         counterClock() {
           this.pageRotate -= 90;
         }
        }
        }
        </script>
        <style  scoped>
        .pdf_btn button {
         color:#367CFD;
        }
        .pdf_wrap {
         background: #fff;
         height: 100vh;
         position: relative;
        }
        .pdf_list {
         height: 100vh;
         overflow: scroll;
        }
        .close {
         position: absolute;
         left: 0;
         bottom: 0;
         height: 60px;
         width: 100%;
         line-height: 40px;
         text-align: center;
         color:#367CFD;
         font-size:30px;
         background: #fff;
        }
        </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    1. vue-pdf 不太友好,网上有说用 vue-pdf-signature 替代,依旧一样的问题。

    2. 安卓显示不全,鸿蒙白屏,ios可以显示。

    网上解决方法:https://blog.csdn.net/PokoMobula/article/details/103164795,未解决问题;https://blog.csdn.net/weixin_44612172/article/details/127783210, 未解决问题imagepng

    1. 引入上面的字体后,安卓直接白屏,iOS依然可以显示。问题依旧。

    4.pfile 代理

        let url = 'https://xxxx?key=xxx.pdf'
        let pfileUrl = 'http://www.pfile.com.cn/api/profile/onlinePreview?url='+encodeURIComponent(url)
        window.open(pfileUrl);
    
    • 1
    • 2
    • 3

    遇到问题:

    1. 三种手机系统都打不开,需要手动转跳到浏览器中打开,浏览器都能正常预览。

    预测方案:按成功方案预测,iframe + pfile 代理,应该也能实现。

  • 相关阅读:
    潘爱民:计算机程序的演进——我的程序人生三十年
    重温C#中的值类型和引用类型
    【OpenCV DNN】Flask 视频监控目标检测教程 01
    了解C语言中的atoi函数和模拟实现
    PL/SQL 集合
    数据结构与算法(七) 二分法
    tomcat10.1.0源码分析
    (2)扩散模型 Diffusion Model 1-2 扩散阶段
    【***操作系统---第三章***】
    【Sentinel Go】新手指南、流量控制、熔断降级和并发隔离控制
  • 原文地址:https://blog.csdn.net/weixin_42717027/article/details/136225233