#yyds干货盘点#前端在线预览PDF文件

Posted 汤圆学Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#yyds干货盘点#前端在线预览PDF文件相关的知识,希望对你有一定的参考价值。

前言

这里用到了vue-pdf插件,预览PDF相关的操作基本都有实现;

我们需要做的就是各种布局(因为需兼容已有的布局,有的地方可能需要修改),比如翻页按钮,页码展示等等;

vue-pdf的GitHub地址:FranckFreiburger/vue-pdf: vue.js pdf viewer (github.com)

目录

  1. 入门例子
  2. 展示所有页码
  3. 翻页操作
  4. 封装组件
  5. 完整代码

正文

1. 入门例子

安装命令:yarn add vue-pdf

最简单的入门例子,如下所示:

<template>
  <pdf src="/pdf/1.pdf"></pdf>
</template>

<script>
import pdf from vue-pdf

export default 
  components: 
    pdf
  

关于本地文件的路径问题:

这里需要注意一下,要把pdf放在public目录下,然后通过/进行引用;

比如你的pdf路径为:public/pdf/1.pdf,那么src就要写成:/pdf/1.pdf

如果是远程路径,则直接赋值;

2. 展示所有页码

上面的入门例子只是展示了第一页的内容,其他内容没有展示,如果需要展示其他页,则需要添加翻页功能;

但是现在我们先简化,不添加翻页功能,而是用v-for直接展示所有的页码;

<template>
    <div>
        <pdf
            v-for="i in numPages"
            :key="i"
            :src="src"
            :page="i"
            style="display: inline-block; width: 25%"
        ></pdf>
    </div>
</template>

<script>

import pdf from vue-pdf

var loadingTask = pdf.createLoadingTask(/pdf/1.pdf);

export default 
    components: 
        pdf
    ,
    data() 
        return 
            src: loadingTask,
            numPages: undefined,
        
    ,
    mounted() 

        this.src.promise.then(pdf => 

            this.numPages = pdf.numPages;
        );
    


</script>

展示效果如下所示:

当我们的页码不是很多时,可以采用这种简单粗暴的方式进行展示,很方便;

但是如果页码过多,则不仅看起来很费劲,而且加载也会很慢,这时就需要用到翻页功能;

3. 翻页操作

这里主要增加两个按钮,以及相关属性,下面是部分代码:

<a-list-item>
    <div @click="changePdfPage(pre)"
         :style="currentPage===1?cursor: not-allowed;:">
        上一页
    </div>
</a-list-item>
<a-list-item>
    <div @click="changePdfPage(next)"
         :style="currentPage===pageCount?cursor: not-allowed;:">
        下一页
    </div>
</a-list-item>
<pdf :src="srcPdf"
     :page="currentPage"
     @num-pages="pageCount=$event"
     style="display: inline-block;width:100%"></pdf>
  • @num-pages 事件:获取pdf的总页数,这里获取到之后传给了pageCount
  • page 属性:就是当前页码,这里通过点击上一页和下一页来修改来更新页码

效果如下所示:

完整代码见下面;

4. 封装组件

为了方便使用,我们可以将上面的预览代码封装成功一个单文件组件,然后在需要的地方进行引入即可;

封装后的组件代码贴到文末了,因为有点长:

我们在展示pdf文件时,可以通过跳转到新标签页的方式进行展示,这样组件内的布局不会有太大的变化;

跳转代码如下所示:

let routeUrl = this.$router.resolve(
              path: /preview-pdf,
              query:pdfPath
          )
window.open(routeUrl.href, _blank)
  • /preview-pdf:这个路径就是配置在路由里面的,预览pdf的路径

  • pdfPath:这里我们是通过query的方式进行传参,然后在预览组件内通过this.srcPdf = decodeURIComponent(this.$route.query.pdfPath)进行获取;

    • > 因为存在编码问题,所以这里需要加上解码操作;

5. 完整代码

完整的封装组件如下,这里是参考网上的例子,做了一些修改

<template>
    <div id="container">
        <!-- 上一页、下一页 -->
        <div class="right-btn">
            <a-space>
                <a-list>
                    <a-list-item>
                        <div >
                            <input v-model.number="currentPage"
                                   type="number"
                                   class="inputNumber"
                                   @input="inputEvent()"> / pageCount
                        </div>
                    </a-list-item>
                    <a-list-item>
                        <div @click="changePdfPage(first)"
                        >
                            首页
                        </div>
                    </a-list-item>
                    <a-list-item>
                        <!-- 在按钮不符合条件时禁用 -->
                        <div @click="changePdfPage(pre)"
                             :style="currentPage===1?cursor: not-allowed;:">
                            上一页
                        </div>
                    </a-list-item>
                    <a-list-item>
                        <div @click="changePdfPage(next)"
                             :style="currentPage===pageCount?cursor: not-allowed;:">
                            下一页
                        </div>
                    </a-list-item>
                    <a-list-item>
                        <div @click="changePdfPage(last)"
                        >
                            尾页
                        </div>
                    </a-list-item>
                </a-list>
            </a-space>
        </div>

        <div class="pdfArea">
            <pdf :src="srcPdf"
                 ref="pdf"
                 :page="currentPage"
                 @num-pages="pageCount=$event"
                 @page-loaded="currentPage=$event"
                 @loaded="loadPdfHandler"
                 @link-clicked="currentPage = $event"
                 style="display: inline-block;width:100%"></pdf>
        </div>
    </div>
</template>

<script>
import pdf from vue-pdf

export default 
    components: 
        pdf
    ,
    computed: 
    ,
    created () 
        console.log(query:, this.$route.query)
        this.srcPdf = decodeURIComponent(this.$route.query.pdfPath)
    ,
    destroyed () 
    ,
    mounted () 

    ,
    data () 
        return 
            // ----- vuepdf -----
            // src静态路径: /static/xxx.pdf
            // src服务器路径: http://.../xxx.pdf
            // src: srcPdf,
            // 当前页数
            currentPage: 0,
            // 总页数
            pageCount: 0,
            // 加载进度
            loadedRatio: 0
        
    ,
    methods: 
        // 页面回到顶部
        toTop () 
            document.getElementById(container).scrollTop = 0
        ,
        // 输入页码时校验
        inputEvent () 
            if (this.currentPage > this.pageCount) 
                // 1. 大于max
                this.currentPage = this.pageCount
             else if (this.currentPage < 1) 
                // 2. 小于min
                this.currentPage = 1
            
        ,
        // 切换页数
        changePdfPage (val) 
            if (val === pre && this.currentPage > 1) 
                // 切换后页面回到顶部
                this.currentPage--
                this.toTop()
             else if (val === next && this.currentPage < this.pageCount) 
                this.currentPage++
                this.toTop()
             else if (val === first) 
                this.currentPage = 1
                this.toTop()
             else if (val === last && this.currentPage < this.pageCount) 
                this.currentPage = this.pageCount
                this.toTop()
            
        ,

        // pdf加载时
        loadPdfHandler (e) 
            // 加载的时候先加载第一页
            this.currentPage = 1
        ,

    

</script>

<style scoped>
#container 
    overflow: auto;
    font-family: PingFang SC;
    width: 100%;
    display: flex;
    position: relative;


/* 功能按钮区 */
.right-btn 
    right:4rem;
    position: fixed;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    z-index: 99;


.pdfArea 
    width: 80%;


/*在谷歌下移除input[number]的上下箭头*/
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button 
    -webkit-appearance: none !important;
    margin: 0;

/*在firefox下移除input[number]的上下箭头*/
input[type=number] 
    -moz-appearance: textfield;


.inputNumber 
    border-radius: 8px;
    border: 1px solid #999999;
    font-size: 18px;
    width: 2rem;
    text-align: center;

.inputNumber:focus 
    border: 1px solid #00aeff;
    background-color: rgba(18, 163, 230, 0.096);
    outline: none;
    transition: 0.2s;


</style>

如何使用?

先注册路由:src/router/index.js

import MyPdf from ../components/MyPdf

export default new VueRouter(
    routes: [
            
                path: /apply-contract-pdf,
                name: apply-contract-pdf,
                component: MyPdf
            ,
])

再通过如下方法进行预览:

previewPdf(pdfPath)
    let routeUrl = this.$router.resolve(
        path: /preview-pdf,
        query:pdfPath
    )
    window.open(routeUrl.href, _blank)
,

总结

本篇介绍了vue-pdf的一些简单使用,包括首页展示、分页展示等;

其实还有一些进度条展示这里没列出来,感兴趣的可以配合a-progress组件和progress属性进行体验

以上是关于#yyds干货盘点#前端在线预览PDF文件的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点 React工作记录六如何实现一个图片的伪预览效果

#yyds干货盘点 React工作记录六如何实现一个图片的伪预览效果

# yyds干货盘点 # 怎么在第一个PDF文件的中间,插入第二个PDF文件的内容?

#yyds干货盘点#前端如何下载文件流

#yyds干货盘点#前端如何通过antdv组件上传文件

#yyds干货盘点# Golang Gin 框架上传介绍