前端怎么预览pdf

1.背景

后台返回了一个在线的pdf地址,需要我这边去做一个pdf的预览(需求1),并且支持配置是否可以下载(需求2),需要在当前页就能预览(需求3)。之前我写过一篇预览pdf的文章,但是当时后台返回的是blob流文件,如果你们的pdf也是以流文件的形式返回的,可以看这篇文章(超链接点进去就行)。

2.简单说下pdf预览的实现方式

复制代码
a.借助 <embed>  /  <iframe>标签

这个是真的很简单,我直接贴在下面了,缺点是: 没办法阻止用户打印和下载pdf,所以我pass了这个方案

复制代码
<embed
 type="application/pdf"
 :src="pdfUrl"
 width="800"
 height="600" />


<iframe
 :src="pdfUrl"
 width="800"
 height="600" />

实现效果:

b.使用vue插件vue-pdf来渲染(应该还有一些其他的插件也可以使用,大家自己研究下实现的效果把)

这个方案我已经试了且用到项目上了,但是感觉很丑,跟浏览器打开pdf的效果差别很大,原因是这个插件大概得原理是把pdf转成了图片然后使用canvas来渲染的,然后很多东西都没有,就被我pass了。你可以想象一下你的pdf,然后你截图放进你网页上的感觉,就差不多是这个效果了,图片我忘记保存了,大家脑补一下

我找了个图,这个其实别人还做了一些其他的渲染,比如下面的也是他自己写的。我感觉是没这么好看的,所以就抛弃了这个

c.使用pdf.js预览

我觉得预览pdf这一块还是得用pdf.js,真的很成熟,样式也还是很给力的,然后想要改成什么样就可以改成什么样,因为源码在你手上。

缺点:稍微麻烦点,需要处理跨域的问题(但是如果你的网站、pdf文件所在位置,后台返回的pdf位置都在同一个域名下的话,就不需要处理)。且可能需要知道一点运维的知识,不然很可能你在本地能运行成功,但是到线上可能访问不到

3.使用pdf.js预览pdf

a.到官网去下载pdf.js

建议下第二个!!!(别问我为啥,因为我下了第一个来写demo发现有报错,又踩坑了)

b.解压之后直接丢到项目中的public文件夹下面去
c.写一个pdf.vue文件,内容如下(注意我的路径,这个路径跟public的路径是一样的,前面加了一个/,原因如下:当我们使用npm run serve时,我们的本地电脑也会开启一个服务将public项目中的资源开发出来,此时跟服务器是一样的,你去访问:localhost:8080/pdf/web/viewer.html 是可以正常访问通的,这里不理解的话,就依葫芦画瓢吧,没关系的 ):
复制代码
<template>
  <iframe :src="'/pdf/web/viewer.html?file='+pdfUrl"></iframe>
</template>
<script>

export default {
  name: 'Pdf',
  props: {
    pdfUrl: {
      type: String,
      default: ''
    }
  }
}
</script>

<style scoped>
iframe {
  /* width: 960px; */
  width: 1100px;
  max-width: 100%;
  height: 800px;
  margin-left: 50%;
  transform: translateX(-50%);
}
</style>
d.在页面中导入使用:
复制代码
<template>
  <div class="home">
    <div>这下面是我用来预览pdf文件的</div>
    <pdf :pdfUrl="pdfUrl"></pdf>
  </div>
</template>

<script>
import pdf from './pdf.vue';

export default {
  name: 'HomeView',
  components:{
    pdf
  },
  data() {
    return {
      pdfUrl:'http://localhost:8080/怎么删除wps中最后的空白页.pdf'
    }
  },
  created(){
    
  },
};
</script>
e.预览效果是这样子的
f.到源码中修改一下把打印和下载都去掉,这一步很简单,大家自己去弄了,也可以直接使用我的pdf文件,我这里都已经改好了。最后的效果如下:

4.难点处理

很大概率你在本地能跑通代码,但是到线上会出问题,可能会出现的问题我都罗列在下面了

a:线上404

线上404的话,说明你线上的这个pdf的资源没有上传到线上,或者线上写的路径不对!比如你的ip为192.168.1.182。如果正常的话,你去访问192.168.1.182/pdf/web/viewer.html 是可以正常访问通的。如果都没有出现正常的这个页面,如下:

那么说明你pdf文件资源没上传或者你写的路径不对。 1.检查dist包里面是否有这个pdf文件(一般放在public文件夹的都会原封不动的打到dist包中,这里还是需要检查下) 2.如果发现有的话,说明没问题,那么你需要到服务器上看下有没有这个pdf文件上传上去了没有。如果有的话,那就是你写的路径不对,或者是后台没有开发这个静态资源文件夹。此时如果你不懂的话,你就跟后台说下你要去访问这个页面,应该要用什么路径去访问才能访问的到。正常来说 192.168.1.182/pdf/web/viewer.html是可以的,如果不可以,可能是要加什么路径,比如192.168.1.182/web/pdf/web/viewer.html这种。如果你是web/pdf/web/viewer.html才能访问的到,那么你就要在你的pdf.vue里面改下路径以对应生产环境

b:线上显示资源跨域

这里是很明显从浏览器面板能看到的。这个的处理,需要你和后台一起处理,首先你访问/pdf/web/viewer.html这个的地址和你访问的页面的地址是需要在一个域名下的(如果不在的话,需要后台处理,开放个别域名),第二点,就是/pdf/web/viewer.htmlfile='+pdfUrl" 这个pdfUrl的地址最好也是跟你的pdf的viewer.html在同一个域名下,相当于三个都在同一域名下,就不会有跨域问题了。如果后台说是静态资源都放到另一台主机上了,那么麻烦他让他做个资源映射,保证你的pdfUrl是跟你的pdf的viewer.html在同一个域名下的

5.demo地址

demo地址可下载自己看代码:https://github.com/rui-rui-an/viewpdf

参考文章:https://juejin.cn/post/7207078219215732794?searchId=2024060423581130C1D707D73A6338E3BA#heading-14

6.更新

关于下载(忘记写下载了)

html:

我这里用的是一个div,然后文件名作为用户下载的入口,点击就能去下载

复制代码
<div class="downpdf" href="#" v-if="is_download" @click="goDownload">{{ pdfname }}</div>
方法1(直接下载):
复制代码
downloadPdf(pdfurl) {
      let fileName = this.pdfname
      let reg = /^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~/])+$/
      if (!reg.test(pdfurl)) {
        throw new Error('传入参数不合法,不是标准的文件链接')
      } else {
        let xhr = new XMLHttpRequest()
        xhr.open('get', pdfurl, true)
        xhr.setRequestHeader('Content-Type', 'application/pdf')
        xhr.responseType = 'blob'
        let that = this
        xhr.onload = function () {
          if (this.status == 200) {
            //接受二进制文件流
            var blob = this.response
            that.downloadExportFile(blob, fileName)
          }
        }
        xhr.send()
      }
    },
    downloadExportFile(blob, tagFileName) {
      let downloadElement = document.createElement('a')
      let href = blob
      if (typeof blob == 'string') {
        downloadElement.target = '_blank'
      } else {
        href = window.URL.createObjectURL(blob) //创建下载的链接
      }
      downloadElement.href = href
      downloadElement.download = tagFileName
           //下载后文件名
      document.body.appendChild(downloadElement)
      downloadElement.click() //点击下载
      document.body.removeChild(downloadElement) //下载完成移除元素
      if (typeof blob != 'string') {
        window.URL.revokeObjectURL(href) //释放掉blob对象
      }
    },
方法二(通过调自己的后端的下载api来下载,这里得问自己的后台,我这里就不贴代码了)
相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom11 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试