Vue项目预览PDF的简单解决方案

6,707 阅读1分钟

需求及引言

最近在项目中,因为有一处需求,需要预览图片/PDF文件,Vue项目,索性采用了element-uidialog组件来展示文件。

图片预览很简单,直接在dialog组件放置一张图片,加入url即可。

但是PDF预览不太好处理,如果想要在dialog中放pdf,就需要用到vue-pdf(或者使用pdf.js,前者封装了后者,在vue中更加好用)

解决方案

采用vue-pdf来展示pdf

地址

安装yarn add vue-pdf

例子

<template>
<!--
    1. src: PDF路径
    2. page:pdf当前页数
    3. @num-pages:pdf的总页数
    4. @page-loaded:加载时获取到页码
-->
// page: PDF的页数
<pdf
    :src="PDF路径"
    :page="pdfPage"
    @num-pages="pdfPageCount = $event"
    @page-loaded="pdfPage = $event"
></pdf>
<!-- 上下翻页 -->
<button @click="previousPage">上一页</button>
<button @click="nextPage">下一页</button>
</template>
<script>
import pdf from 'vue-pdf'
export default {
    components: {
        pdf
    },
    data() {
        return {
          pdfPage: 1,
          pdfPageCount: 1,
        }
    },
    methods: {
        // 上一页
        previousPage() {
          let p = this.pdfPage;
          p = p > 1 ? p - 1 : this.pdfPageCount;
          this.pdfPage = p;
        },
        // 下一页
        nextPage() {
          let p = this.pdfPage;
          p = p < this.pdfPageCount ? p + 1 : 1;
          this.pdfPage = p;
        }
    }
}
</script>
<style></style>

此时,我们已经可以将一个PDF嵌入到页面中了。

存在的问题

1. 读取增加进度条

因为PDF会有过大的问题,所以为了提高用户体验,在加载PDF的时候会有一个进度条。由于本项目通过axios来进行HTTP请求,所以:

axios.create({
     url: 'aabbcc',
     method: 'GET',
     responseType: 'blob',
     // 在创建 axios 的实例时
     // 这个时用来处理原生download的事件的
     onDownloadProgress: progressEvent => { handleDownloadProgress(progressEvent) }
})

// 处理进度条问题
function handleDownloadProgress(e) {
    // e.loaded 已经载入的
    // e.total  所有
    console.log(e.loaded / e.total)
}

可以通过onDownloadProgress来进行自定义处理进度条

2. 中文不展示

如果在读取PDF时,出现以下报错信息:

Warning: Error during font loading: The CMap “baseUrl” parameter must be specified, ensure that the “cMapUrl” and “cMapPacked” API parameters are provided.

在使用vue-pdf的组件中,

// 1. 引入
import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js';

// 2. 在使用时
this.pdfUrl = pdf.createLoadingTask({
    url,
    CMapReaderFactory
});
// 如果仍报错,就使用 CDN 加载 cMap
this.pdfUrl = pdf.createLoadingTask({
    url,
    cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/', 
    cMapPacked: true
});

3. webpack 打包后出现[hash].worker.js

打包后在根路径会出现 worker.js 且,无法预览 pdf

解决方案:

找到node_modules/worker-loader/dist/index.js

const filename = _loaderUtils2.default.interpolateName(this, options.name || '[hash].worker.js', {

修改为 👇

const filename = _loaderUtils2.default.interpolateName(this, options.name || 'static/js/[hash].worker.js', {

这样打包后的worker.js文件就会存在于/static/js/