前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Vue 通过调用文件流实现 PDF 文件在线预览的方法

Vue 通过调用文件流实现 PDF 文件在线预览的方法

作者头像
小焱
发布2025-05-19 16:28:52
发布2025-05-19 16:28:52
81300
代码可运行
举报
文章被收录于专栏:前端开发前端开发
运行总次数:0
代码可运行

在Vue项目中实现PDF文件流的预览,有多种可行的方案,以下为你详细介绍:

方案一:利用浏览器原生支持

如果后端返回的是PDF文件在服务器上的路径,直接访问该路径即可在浏览器中预览PDF文件。例如,后端返回路径http://example.com/path/to/file.pdf,在前端可以通过如下方式实现预览:

代码语言:html
复制
<template>
  <div>
    <iframe :src="pdfUrl" frameborder="0" style="width: 100%; height: 800px"></iframe>
  </div>
</template>

<script>
export default {
  data() {
    return {
      pdfUrl: 'http://example.com/path/to/file.pdf'
    }
  }
}
</script>

当后端返回的是PDF文件流时,直接访问文件流接口,浏览器会默认下载该PDF文件。此时,需要对接口的响应头进行设置:

代码语言:txt
复制
Content-Disposition: inline;filename=<pdf的文件名>

Content-Disposition有两个值:attachment表示下载文件,inline表示内嵌显示。上述设置是告诉浏览器,当前接口返回的文件流是PDF格式,且需要内嵌显示,即预览。假设后端接口为/api/getPdfStream,在Vue中可以这样调用:

代码语言:javascript
代码运行次数:0
运行
复制
export function getPdfStream() {
  return axios.get('/api/getPdfStream', {
    responseType: 'arraybuffer',
    headers: {
      'Content-Disposition': 'inline;filename=example.pdf'
    }
  })
}

在组件中使用:

代码语言:html
复制
<template>
  <div>
    <button @click="previewPdf">预览PDF</button>
  </div>
</template>

<script>
import { getPdfStream } from '@/api/pdf'
export default {
  methods: {
    async previewPdf() {
      try {
        const response = await getPdfStream()
        const blob = new Blob([response.data], { type: 'application/pdf' })
        const url = window.URL.createObjectURL(blob)
        window.open(url)
      } catch (error) {
        console.error('预览PDF失败', error)
      }
    }
  }
}
</script>

方案二:使用PDF.js

  1. 引入PDF.js
    • 到PDF.js官网下载PDF.js插件并解压。
    • 在Vue项目根目录下创建static文件夹(若已存在则无需重复创建),在static下新建pdf文件夹,并将解压后的PDF.js文件放在该目录中。
    • 通过copy-webpack-plugin插件将static文件夹下的静态资源复制到dist目录,确保开启本地服务或上线后能访问到静态资源。首先安装copy-webpack-plugin
代码语言:bash
复制
npm install copy-webpack-plugin --save-dev

然后在webpack.config.js中进行配置:

代码语言:javascript
代码运行次数:0
运行
复制
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
  // 其他配置项
  plugins: [
    new CopyWebpackPlugin({
      patterns: [
        {
          from:'static',
          to: 'static'
        }
      ]
    })
  ]
}
  1. 使用PDF.js进行预览 利用PDF.js提供的viewer.html文件来预览PDF文件。假设后端返回的PDF文件地址为pdfFileUrl:<template> <div> <button @click="previewPdf">预览PDF</button> </div> </template> <script> export default { methods: { previewPdf() { const pdfFileUrl = 'http://example.com/path/to/pdf' window.open(`/static/pdf/viewer.html?file=${encodeURIComponent(pdfFileUrl)}`) } } } </script>如果后端返回的是文件流,需要先将文件流处理成可被PDF.js识别的格式:<template> <div> <button @click="previewPdf">预览PDF</button> </div> </template> <script> import pdfjsLib from 'pdfjs-dist' import axios from 'axios' export default { methods: { async previewPdf() { try { const response = await axios.get('/api/getPdfStream', { responseType: 'blob' }) const blob = new Blob([response.data], { type: 'application/pdf' }) const data = await blob.arrayBuffer() const loadingTask = pdfjsLib.getDocument({ data }) const pdf = await loadingTask.promise const page = await pdf.getPage(1) const canvas = document.createElement('canvas') const context = canvas.getContext('2d') const viewport = page.getViewport({ scale: 1 }) canvas.height = viewport.height canvas.width = viewport.width await page.render({ canvasContext: context, viewport }).promise const img = new Image() img.src = canvas.toDataURL('image/png') document.body.appendChild(img) } catch (error) { console.error('预览PDF失败', error) } } } } </script>方案三:使用vue - pdf插件npm install vue-pdf --saveimport pdf from 'vue-pdf' import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory' export default { components: { pdf, CMapReaderFactory } }如果后端返回文件流,先将文件流转换为Blob,再转换为ObjectURL:<template> <div> <pdf :src="pdfUrl" :page="1"></pdf> </div> </template> <script> import pdf from 'vue-pdf' import axios from 'axios' export default { components: { pdf }, data() { return { pdfUrl: '' } }, methods: { async getPdfStream() { try { const response = await axios.get('/api/getPdfStream', { responseType: 'blob' }) const blob = new Blob([response.data], { type: 'application/pdf' }) this.pdfUrl = window.URL.createObjectURL(blob) } catch (error) { console.error('获取PDF文件流失败', error) } } }, mounted() { this.getPdfStream() } } </script>
  2. 安装依赖
  3. 引入并使用 在需要使用的组件中引入:

应用实例

假设我们正在开发一个文档管理系统,用户需要在系统中预览合同文件(以PDF格式存储)。后端提供了一个接口/api/contracts/{id}/pdf,该接口根据合同ID返回对应的PDF文件流。

  1. 使用浏览器原生支持的实现ContractPreview.vue组件中:
代码语言:html
复制
<template>
  <div>
    <h2>合同预览</h2>
    <button @click="previewContract">预览合同</button>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  methods: {
    async previewContract() {
      const contractId = 1 // 假设合同ID为1,实际应用中从路由或其他地方获取
      try {
        const response = await axios.get(`/api/contracts/${contractId}/pdf`, {
          responseType: 'arraybuffer'
        })
        const blob = new Blob([response.data], { type: 'application/pdf' })
        const url = window.URL.createObjectURL(blob)
        window.open(url)
      } catch (error) {
        console.error('预览合同失败', error)
      }
    }
  }
}
</script>
  1. 使用PDF.js的实现ContractPreview.vue组件中:
代码语言:html
复制
<template>
  <div>
    <h2>合同预览</h2>
    <button @click="previewContract">预览合同</button>
  </div>
</template>

<script>
import pdfjsLib from 'pdfjs-dist'
import axios from 'axios'

export default {
  methods: {
    async previewContract() {
      const contractId = 1
      try {
        const response = await axios.get(`/api/contracts/${contractId}/pdf`, { responseType: 'blob' })
        const blob = new Blob([response.data], { type: 'application/pdf' })
        const data = await blob.arrayBuffer()
        const loadingTask = pdfjsLib.getDocument({ data })
        const pdf = await loadingTask.promise
        const page = await pdf.getPage(1)
        const canvas = document.createElement('canvas')
        const context = canvas.getContext('2d')
        const viewport = page.getViewport({ scale: 1 })
        canvas.height = viewport.height
        canvas.width = viewport.width
        await page.render({ canvasContext: context, viewport }).promise
        const img = new Image()
        img.src = canvas.toDataURL('image/png')
        document.body.appendChild(img)
      } catch (error) {
        console.error('预览合同失败', error)
      }
    }
  }
}
</script>
  1. 使用vue - pdf插件的实现ContractPreview.vue组件中:
代码语言:html
复制
<template>
  <div>
    <h2>合同预览</h2>
    <pdf :src="pdfUrl" :page="1"></pdf>
  </div>
</template>

<script>
import pdf from 'vue-pdf'
import axios from 'axios'

export default {
  components: {
    pdf
  },
  data() {
    return {
      pdfUrl: ''
    }
  },
  methods: {
    async getContractPdf() {
      const contractId = 1
      try {
        const response = await axios.get(`/api/contracts/${contractId}/pdf`, { responseType: 'blob' })
        const blob = new Blob([response.data], { type: 'application/pdf' })
        this.pdfUrl = window.URL.createObjectURL(blob)
      } catch (error) {
        console.error('获取合同PDF失败', error)
      }
    }
  },
  mounted() {
    this.getContractPdf()
  }
}
</script>

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方案一:利用浏览器原生支持
  • 方案二:使用PDF.js
  • 应用实例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档