vue项目中使用pdf.js预览pdf文件

2023-11-18

项目要求需要预览pdf文件,网上找了很久,大多数都是推荐pdf.js,自己起了解了一下,最后决定用pdf.js,

但是发现,在vue中使用这个很少!!!!!所以我就写这一篇帮助一下vue使用pdfjs的朋友!

其实 这和前端框架无关的,直接使用pdf.js原生

     搜多了你就发现有几个封装pdf.js的vue组件,个人试验了其中一个,效果不是很好,所以,当然啊,用原生

的是最好的啦!

   首先肯定是导入插件,我是从官网直接下载,链接:点击打开链接,注意放在static文件目录下,

这里面有核心的pdf.js和pdf.worker.js,以及展示pdf的viewer页面把它作为静态资源来编译,基本想要的build和web这两个重要文件夹的东西都正常编译。当然你可以可以npm install一下,整个文件放在static目录下的不好地方就是打包会很大哟,我不是图方便嘛。目录结构放一下

其实就可以直接用的,网上很多,viewer.js 里的 代表着文件路径,如果你项目中有个pdf文件,那直接相对路径就可以在页面预览,我今天说的是远程预览(服务器端url预览),pdf.js也提供了一种方法,用file= 的方式也可以打开哟,放在页面上使用,我是iframe进行嵌套

    用这种方式必不可少的是跨域问题,你存储文件的服务器路径会和项目产生跨域,我的解决办法是,让后台返回流的形式返回文件,后台代码案例: 

注意:

 

1    pdf.js是不支持跨域文件加载的  直接加载是不会成功的。会报  “file origin doesnot match viewer”错误。 所以我们得改变一下源码

把这句警告直接注释就行了

 

2    file参数中默认只允许传简单路径比如:http://www.a.com/file.php.  如果你要浏览的pdf路径为http://www.a.com/file.php?id=2001。 这时候直接传入的话会解析出错, 因为pdf.js无法判断id=2001是viewer.html的参数呢还是file.php的参数

 这告诉我们 url必须进行encode编码  把参数file后传入的动态参数中特殊字符转义:

这里又会有两种方法:

encodeURI() 把字符串编码为 URI
encodeURIComponent() 把字符串编码为 URI 组件

发现        encodeURI不会对:/?&等uri中起分割作用的字符进行编码;

encodeURIComponent则会。

所以必须选择 encodeURIComponent 进行对url的编码

举例:

这样如此就ok了

 

3  

如果 后台返回给前台的流的url形式 是

https://uat.hjl.hscf.com/api/esm/v1/contractTemplates/load?id=13&access_token=a33e14ef6aba87b593b1aac31e3d97bb

这样pdf.js插件是无法识别的,所以的在最后加上 &.pdf  来骗过插件

效果图

上面是pc端的,移动端也同样试用

根据以上在实现在项目中

组件代码 

<template>
    <div class="cpdf">
        <div class="center">
            <div class="contor">
            </div>
            <canvas v-for="data in canvasData" :key="data" class="canvasstyle" :id="'the-canvas-'+data"></canvas>
        </div>
        <div class="page-foot">
            <Page :current="page_num" :total="PageCount" @on-change="orientation" simple style="display: inline-block;"></Page>
            <div class="foot-button">
                <Button @click="addscale" icon="plus" size="small" style="margin-right:20px;" title="放大"></Button>
                <Button @click="minus" icon="minus" size="small" title="缩小"></Button>
            </div>
        </div>
    </div>
</template>

<script type="text/ecmascript-6">
import { Button, Page, Affix } from "iView";
import PDFJS from "../../../static/PDF/pdf.js";

export default {
  name: "CPdf",
  props: ["pdfurl"],
  components: {
    Button: Button,
    Page: Page,
    Affix: Affix
  },
  data() {
    return {
      pdfDoc: null, //pdfjs 生成的对象
      pageNum: 1, //
      pageRendering: false,
      pageNumPending: null,
      scale: 1.2, //放大倍数
      page_num: 0, //当前页数
      page_count: 0, //总页数
      maxscale: 2, //最大放大倍数
      minscale: 0.8, //最小放大倍数
      canvasData: []
    };
  },
  methods: {
    renderPage(num) {
      //渲染pdf
      let vm = this;
      this.pageRendering = true;
      let canvas = document.getElementById("the-canvas-" + num);
      // Using promise to fetch the page
      this.pdfDoc.getPage(num).then(function(page) {
        var viewport = page.getViewport(vm.scale);
        //alert(vm.canvas.height)
        canvas.height = viewport.height;
        canvas.width = viewport.width;

        // Render PDF page into canvas context
        var renderContext = {
          //   canvasContext: vm.ctx,
          canvasContext: canvas.getContext("2d"),
          viewport: viewport
        };
        var renderTask = page.render(renderContext);

        // Wait for rendering to finish
        renderTask.promise.then(function() {
          vm.pageRendering = false;
          if (vm.pageNumPending !== null) {
            // New page rendering is pending
            vm.renderPage(vm.pageNumPending);
            vm.pageNumPending = null;
          }
        });
      });
      vm.page_num = vm.pageNum;
    },
    addscale() {
      //放大
      if (this.scale >= this.maxscale) {
        return;
      }
      this.scale += 0.1;
      for (var i = 1; i < this.canvasData.length + 1; i++) {
        this.queueRenderPage(i);
      }
    },
    minus() {
      //缩小
      if (this.scale <= this.minscale) {
        return;
      }
      this.scale -= 0.1;
      for (var i = 1; i < this.canvasData.length + 1; i++) {
        this.queueRenderPage(i);
      }
    },
    queueRenderPage(num) {
      this.renderPage(num);
    },
    orientation(events) {
      // 用 class="canvasstyle" 添加锚点
      let _index = events;
      //   console.log(_index);
      let jump = document.querySelectorAll(".canvasstyle");
      //   console.log(jump);
      // 获取需要滚动的距离
      let total = 92;
      for (let index = 0; index < _index; index++) {
        if (index > 0) {
          total += jump[index].clientHeight + 5;
        }
      }
      let distance =
        document.documentElement.scrollTop || document.body.scrollTop;
      // 平滑滚动,时长500ms,每10ms一跳,共50跳
      let step = total / 50;
      if (total > distance) {
        smoothDown();
      } else {
        let newTotal = distance - total;
        step = newTotal / 50;
        smoothUp();
      }
      function smoothDown() {
        if (distance < total) {
          distance += step;
          document.body.scrollTop = distance;
          document.documentElement.scrollTop = distance;
          setTimeout(smoothDown, 10);
        } else {
          document.body.scrollTop = total;
          document.documentElement.scrollTop = total;
        }
      }
      function smoothUp() {
        if (distance > total) {
          distance -= step;
          document.body.scrollTop = distance;
          document.documentElement.scrollTop = distance;
          setTimeout(smoothUp, 10);
        } else {
          document.body.scrollTop = total;
          document.documentElement.scrollTop = total;
        }
      }
    }
  },
  computed: {
    ctx() {
      let id = document.getElementById("the-canvas");
      return id.getContext("2d");
    },
    PageCount() {
      return this.page_count * 10;
    }
  },
  mounted() {
    let vm = this;
    vm.canvasData = [];
    // PDFJS.workerSrc = "../../../static/PDF/build/pdf.worker.js";
    PDFJS.getDocument(vm.pdfurl)
      .then(function(pdfDoc_) {
        //初始化pdf
        vm.pdfDoc = pdfDoc_;
        vm.page_count = vm.pdfDoc.numPages;
        for (var i = 0; i < vm.page_count; i++) {
          vm.canvasData.push(i + 1);
        }
        return pdfDoc_;
      })
      .then(function(pdfDoc_) {
        //初始化pdf
        vm.pdfDoc = pdfDoc_;
        vm.page_count = vm.pdfDoc.numPages;
        for (var i = 0; i < vm.page_count; i++) {
          vm.renderPage(i + 1);
        }
      });
  }
};
</script>

<style lang="scss" scoped type="text/css">
.cpdf {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 99999;
  display: flex;
  justify-content: center;
  align-items: center;
  .center {
    text-align: center;
    height: 100%;
    overflow: auto;
    padding-top: 20px;
    .contor {
      margin-bottom: 10px;
    }
  }
  .page-foot {
    position: fixed;
    left: 0px;
    bottom: 0px;
    width: 100%;
    height: 56px;
    line-height: 56px;
    background-color: #fff;
    text-align: center;
    z-index: 10;
    .foot-button {
        display: inline-block;
        height: 56px;
        position: relative;
        top: -22px;
        left: 20px;
    }
  }
}
</style>

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue项目中使用pdf.js预览pdf文件 的相关文章

随机推荐

  • Qt一个信号关联多个槽传输数据

    测试描述 一个TCP服务 三个处理线程 tcp接收的数据传输至三个线程使用 使用信号与槽进行通讯 信号与槽连接如下 关联1 connect tcpServer SIGNAL recBytes QByteArray panorama SLOT
  • Java Beans 介绍

    Java版本 8 写JavaBeans组件 编写JavaBeans组件非常简单 您不需要特殊的工具 也不需要实现任何接口 编写bean只是遵循某些编码约定的问题 您所要做的就是使您的类看起来像一个bean 使用bean的工具将能够识别和使用
  • 淘宝问问:电商AI,重新定义购物体验

    AI大模型进展的如火如荼 怎么少得了电商平台的参与 淘宝率先打响了第一枪 每一个软件都会有自己的 Copilot 淘宝的就叫 淘宝问问 用户可以在淘宝上使用 淘宝问问 来获取商品信息 价格 评价等 当前是内测版 虽有惊喜 但终究是刚刚发布内
  • 同态加密的原理详解与go实践

    学习资料来源 知乎VenusBlockChain https zhuanlan zhihu com p 110210315 知乎刘巍然 https www zhihu com question 27645858 answer 3759850
  • 空间注意力机制_计算机视觉中attention机制的理解

    一 前言 简介 对于attention机制的理解 在看了attention is all you need这篇文章和参考网上一些文章之后 做一个简单的理解和总结 在 attention is all you need 的这篇文章中给出了在n
  • PySide6-控件教程-006-QLabel标签控件-信号

    QLabel 标签控件 本文摘录自我的开源教程 PySide6 代码式教程 QLabel CSDN 平台仅做镜像 答疑 纠错请至 GitHub 提交 issue 信号 QLabel的可用信号只有链接被悬停 链接被点击两种 具体如下 link
  • 金融安全视角农民投资理财的实证研究——以X县为例

    金融安全视角农民投资理财的实证研究 以X县为例 摘要 近年来 随着经济全球化进程的推进 国民收入逐年增加 人们的经济意识也在一定程度上提高 适当的投资和财务管理正在迅速发展 然而 大部分调查数据显示 农民面临的诸多问题还有很多其他原因 包括
  • Qt技巧:QTextEdit显示网络图片

    Qt5的QNetworkAccessManager 类可以很方便的访问网络资源 QNetworkRequest类可以用于发送网络请求 而QNetworkReply则负责接收处理网络资源 今天遇到一个问题 如何在QTextEdit上显示一张网
  • 字节跳动(今日头条),为何战斗力如此凶猛?

    本文转载自公众号 中产之路 年前 一位久未联系的朋友问京杭君 有没有研究过今日头条 还有没有上升空间 这位朋友在杭州阿里工作多年 后出来创业 有猎头联系他 今日头条要在杭州成立技术中心 招负责人 那时候 今日头条 还是这间公司最重要的产品
  • 编辑器Vim

    vi简介 vi是 Visual interface 的简称 它在Linux上的地位就仿佛Edit程序在DOS上一样 它可以执行输出 删除 查找 替换 块操作等众多文本操作 而且用户可以根据自己的需要对其进行定制 Vi不是一个排版程序 它不象
  • 蓝牙耳机BES 2300P 主从配对连接,以及主从自定义收发数据

    恒玄SDk预留了用户接口位于app ibrt customif cmd cpp 中 发送数据的前提是进行主从配对连接 sdk给与了两种模式 IBRT SEARCH UI 未定义时我们可以自己定义主从蓝牙地址 IBRT SEARCH UI 定
  • 服务器系统能耗,服务器能耗怎么计算

    服务器能耗怎么计算 内容精选 换一换 DESS磁盘扩容成功后 需要在裸金属服务器的操作系统中对扩容部分的磁盘分配分区 已登录裸金属服务器 详细操作请参见 裸金属服务器用户指南 中章节 登录Windows裸金属服务器 已挂载磁盘至裸金属服务器
  • JS实现约瑟夫环

    传说罗马人占领了乔塔帕特 41 个犹太人被围堵在一个山洞里 他们拒绝被俘虏 而决定集体自杀 大家决定了一个自杀方案 41 个人围成一个圈 由第 1 个人开始顺时针报数 每报数为 3 的人立刻自杀 然后再由下一个人重新从 1 开始报数 依旧是
  • 笔记本电脑微信视频对方却听不到声音

    我真的是把网上的所有教程 试遍了都没弄好 我自己突发奇想要不然更新下 结果就成功了 首先可以先看看是不是微信版本的原因 麦克风出现问题了 右击我的电脑 gt 属性 gt 设备管理器 gt 音频输入和输出 gt 右击麦克风 gt 更新驱动程序
  • 数值分析Matlab二维正态(高斯)分布以及协方差矩阵

    数值分析Matlab二维正态 高斯 分布以及协方差矩阵 主要是使用了matlab的mvnrnd产生随机的正态 高斯 分布二维矩阵 然后绘制出来 代码运行结果生成的正态分布实验数据如图 MATLAB代码 mu1 0 0 sigma1 4 2
  • ACM输入输出

    写在前面 主要记录一下ACM输入输出的写法 一 输入数值 1 给定N的定长多行输入 题目 https ac nowcoder com acm contest 5657 B 代码 include
  • 【Java】基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法

    Java 基于朴素贝叶斯算法破解基于哈希表的随机字符替换加密算法 不用看了 这篇文章是错的 得出的结果也不是正确的结果 我想错了 因为这个解密算法的前提是已经知道哈希表的情况下去计算的 而实际上应该是只靠统计去分析密文 所以实际破解所需要的
  • Unity模型导入相关知识

    文章目录 常见的模型格式 模型导入参数设置 Model页签 Scene设置 Meshes设置 Geometry设置 Rig页签 Animation Type 动画类型 Avatar化身信息设置 Animation页签 基础信息设置 动画剪辑
  • 童年回忆——切水果(内含源码inscode一键运行)

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 React从入门到精通 前端炫酷代码分享 从0到英雄 vue成神之路 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架
  • vue项目中使用pdf.js预览pdf文件

    项目要求需要预览pdf文件 网上找了很久 大多数都是推荐pdf js 自己起了解了一下 最后决定用pdf js 但是发现 在vue中使用这个很少 所以我就写这一篇帮助一下vue使用pdfjs的朋友 其实 这和前端框架无关的 直接使用pdf