Vue3 实现 PDF 预览与下载 缩放 上一页和下一页 放大和 缩小 功能

标题:Vue3 实现 PDF 预览与下载功能

在现代的 Web 应用程序中,PDF 文件是一种非常常见的文件格式,因为它在多个平台和设备上都能保持一致的文档格式,并且不易受病毒攻击。因此,在许多项目中实现 PDF 预览和下载功能是非常必要的。本文将介绍如何使用 Vue3 和 PDF.js 实现 PDF 预览和下载功能。

PDF 预览功能的实现

在本次教程中,我们将使用 Vue3 和 vue-pdf-embed 插件来实现 PDF 预览功能。vue-pdf-embed 是一个基于 PDF.js 的 Vue 组件库,可以轻松嵌入 PDF 文件并进行预览。

首先,我们需要安装 vue-pdf-embed vue3-pdfjs 依赖:

npm install vue-pdf-embed@1.2.1
npm install vue3-pdfjs@0.1.6

接着,在 Vue3 组件中引入 vue-pdf-embed 并定义 PDF 预览的相关参数:

html 复制代码
<template>
  <a-spin :spinning="state.loading" tip="加载中...">
    <div class="pdf-preview">
      <div class="pdf-wrap">
        <vue-pdf-embed
          :page="state.pageNum"
          :source="state.source"
          :style="scale"
          class="vue-pdf-embed"
        />
      </div>
      <div class="page-tool">
        <div class="page-tool-item" @click="lastPage">上一页</div>
        <div class="page-tool-item" @click="nextPage">下一页</div>
        <div class="page-tool-item">
          {{ state.pageNum }}/{{ state.numPages }}
        </div>
        <div class="page-tool-item" @click="pageZoomOut">放大</div>
        <div class="page-tool-item" @click="pageZoomIn">缩小</div>
        <div class="page-tool-item" @click="downloadPDF">下载</div>
      </div>
    </div>
  </a-spin>
</template>
<script lang="ts" setup>
import VuePdfEmbed from "vue-pdf-embed";
import { createLoadingTask } from "vue3-pdfjs";

import { reactive, onMounted, computed } from "vue";

const props = defineProps({
  pdfUrl: {
    type: String,
    required: true,
  },
});

const state = reactive({
  source: props.pdfUrl, // 预览pdf文件地址
  pageNum: 1, //当前页面
  scale: 1, // 缩放比例
  numPages: 0, // 总页数
  loading: "",//加载效果
});
// 下载pdf
function downloadPDF() {
  fetch(encodeURI(props.pdfUrl)).then((res) => {
    res.blob().then((myBlob) => {
      const href = URL.createObjectURL(myBlob);
      const a = document.createElement("a");
      a.href = href;
      a.download = "report.pdf"; // 下载文件重命名,并指定文件扩展名为 ".pdf"
      document.body.appendChild(a); // 将<a>元素添加到文档中,以便进行点击下载
      a.click();
      document.body.removeChild(a); // 下载完成后移除<a>元素
    });
  });
}

onMounted(() => {
  const loadingTask = createLoadingTask(state.source);
  state.loading = true; // 添加一个loading状态
  loadingTask.promise.then((pdf: { numPages: number }) => {
    state.numPages = pdf.numPages;
    state.loading = false; // 加载完成后将loading状态设置为false
  });
});

const scale = computed(() => `transform:scale(${state.scale})`);

function lastPage() {
  if (state.pageNum > 1) {
    state.pageNum -= 1;
  }
}

function nextPage() {
  if (state.pageNum < state.numPages) {
    state.pageNum += 1;
  }
}

function pageZoomOut() {
  if (state.scale < 2) {
    state.scale += 0.1;
  }
}

function pageZoomIn() {
  if (state.scale > 1) {
    state.scale -= 0.1;
  }
}
</script>
<style lang="css" scoped>
.pdf-preview {
  position: relative;
  height: 100%;
  padding: 20px 0;
  box-sizing: border-box;
  background-color: #e9e9e9;
}

.pdf-wrap {
  overflow-y: auto;
}

.vue-pdf-embed {
  text-align: center;
  width: 515px;
  border: 1px solid #e5e5e5;
  margin: 0 auto;
  box-sizing: border-box;
}

.page-tool {
  position: absolute;
  bottom: 35px;
  padding-left: 15px;
  padding-right: 15px;
  display: flex;
  align-items: center;
  background: rgb(66, 66, 66);
  color: white;
  border-radius: 19px;
  z-index: 100;
  cursor: pointer;
  margin-left: 50%;
  transform: translateX(-50%);
}

.page-tool-item {
  padding: 8px 15px;
  padding-left: 10px;
  cursor: pointer;
}
</style>

父组件使用

html 复制代码
 <PdfPreview v-if="data && data.content" :pdfUrl="data.content" />

代码解释:

使用 组件来进行 PDF 预览; 使用组件参数 :source 来定义 PDF 文件的地址; 使用组件参数 :page 来定义当前预览页码; 使用组件参数 :style 来定义文档缩放比例; 定义 downloadPDF() 函数用于下载 PDF 文件; 在 onMounted() 钩子函数中使用 createLoadingTask() 方法加载 PDF 文件,并获取总页数; 使用 reactive 创建响应式数据,包括 PDF 文件地址、当前页码、缩放比例和总页数; 使用计算属性 scale 计算文档缩放比例; 定义函数 lastPage() 和 nextPage() 用于实现页面翻页功能; 定义函数 pageZoomIn() 和 pageZoomOut() 用于实现文档缩放功能。 PDF 下载功能的实现

在上面的代码中,我们已经编写了 downloadPDF() 函数,用于实现 PDF 文件的下载。该函数使用 fetch 获取文件数据并将其转换为 blob 对象,然后创建一个 标签并设置其 href 属性为 blob 对象的 URL,最后在文档中插入该标签并模拟点击该标签以实现下载。

相关推荐
慧一居士14 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead16 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说8 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409198 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app