需求说明

  • 实现一个通过vue,预览pdf,并支持滚动加载,可下载的插件

一、下载插件 vue-pdf

npm install --save vue-pdf

二、创建组件

  • 在src/components/下创建pdfAll.vue
<template>
    <div class="pdf-all-container">
        <div class="tool-container">
            <el-button
                style="float: right; margin-left: 20px; padding: 6px 15px"
                type="primary"
                size="mini"
                icon="el-icon-download"
                @click="onDownloadFile"
            >
                下载
            </el-button>
            <span style="float: left; color: #666">{{ numPages }}</span>
            <span
                v-if="loadedRatio > 0 && loadedRatio < 100"
                style="float: left; color: #999; margin-left: 50px; display: inline-block"
            >
                已加载:{{ loadedRatio }}%
            </span>
        </div>
        <div v-loading="loading" v-infinite-scroll="onScrollBtm" class="pdf-viewer">
            <pdf
                v-for="i in numLoadPages"
                :key="i"
                :src="srcTask"
                :page="i"
                style="display: inline-block; width: 100%"
                @progress="loadedRatio = $event"
            />
            <el-empty v-if="loadError" description="预览加载失败,请重新打开!" />
        </div>
    </div>
</template>

<script>
import { queryFile } from '@/api/upload'//获取上传的文件
import pdf from 'vue-pdf' //引入下载的vue-pdf
import { download } from '@/utils' //封装的下载方法

export default {
    components: {
        pdf
    },
    props: {
        fileId: {
            type: String,
            default: void 0
        }
    },
    data() {
        return {
            srcTask: void 0,
            numPages: 0,
            numLoadPages: 0,
            loading: false,
            src: void 0,
            fileInfo: {},
            loadError: false,
            loadedRatio: 0
        }
    },
    watch: {
        //实现监听,父组件需要传过来fileId,通过fileId拼接src地址,以此来显示pdf
        fileId: {
            handler: function(val) {
                if (!val) return
                this.loading = true
                queryFile({
                    id: this.fileId
                })
                    .then(result => {
                        // this.loading = false
                        const fileInfo = result.data
                        console.log(fileInfo)
                        this.src = fileInfo.relatPath + fileInfo.fileName.split('.')[0] + '.pdf'
                        this.fileInfo.src = fileInfo.relatPath + fileInfo.fileName
                        this.fileInfo.realName = fileInfo.realName
                    })
                    .catch(err => {
                        this.loading = false
                        console.log({ err })
                    })
            },
            immediate: true
        },
        src: {
            handler: function(val) {
                if (!val) {
                    return
                }
                this.srcTask = pdf.createLoadingTask(val)
                this.srcTask.onProgress = val => {
                    let ratio = (val.loaded / val.total) * 100
                    if (ratio >= 100) {
                        ratio = 100
                        this.loading = false
                    }
                    this.loadedRatio = ratio.toFixed(2)
                }
                this.srcTask.promise
                    .then(pdf => {
                        console.log({ pdf })
                        this.numPages = pdf.numPages
                        this.numLoadPages = pdf.numPages > 4 ? 4 : pdf.numPages
                        this.fileInfo.pageNum = pdf.numPages
                        this.$emit('loaded', this.fileInfo)
                    })
                    .catch(err => {
                        this.loadError = true
                        console.log(err)
                    })
            },
            immediate: true
        }
    },
    methods: {
        //加载pdf,每4页进行更新
        onScrollBtm() {
            if (this.numLoadPages >= this.numPages) {
                return
            }
            if (this.numLoadPages + 4 > this.numPages) {
                this.numLoadPages = this.numPages
                return
            }
            this.numLoadPages += 4
        },
        //下载pdf
        onDownloadFile() {
            // window.open(this.fileInfo.src + '?attname=' + this.fileInfo.realName)
            download(this.fileInfo.src, this.fileInfo.realName)
        }
    }
}
</script>

<style scoped>
.pdf-all-container {
    width: 100%;
    height: 100%;
    margin: 0 auto;
    overflow: auto;
    position: relative;
}

.tool-container {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 30px;
    /* background: pink; */
}

.pdf-viewer {
    position: absolute;
    left: 0px;
    right: 0;
    top: 40px;
    bottom: 0;
    overflow: auto;
    padding: 10px 20px;
}

.pdf-viewer > span {
    box-shadow: 0px 1px 6px #ddd;
    margin-bottom: 10px;
    border-radius: 7px;
}
</style>

三、下载文件download 方法(src/utils/index.js中)

/**
 * 下载文件
 * @param {String} url 文件下载地址
 * @param {*} name 下载后文件名
 */
export function download(url, name) {
    const a = document.createElement('a')
    a.download = name
    a.href = url
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
}

四、具体实现

  • 引入pdfAll组件
import PdfAll from '@/components/common/pdfAll.vue'
  • 注册组件
components: {
        PdfAll
    },
  • 使用组件
<div class="pdf-container">
     <pdf-all ref="pdfViewer" :file-id="fileId" @loaded="onPdfLoaded" />
</div>
data() {
        return {
            fileId: void 0
        }
    },
    methods: {
        onPdfLoaded(file) {
            console.log({ file })
        },
    }

五、传递fileId

这一步需要大家自己通过接口,获取id,然后赋值给fileId就可以啦

六、实现预览

QQ录屏20220330113239

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐