在Vue项目中实现PDF文件流的预览,有多种可行的方案,以下为你详细介绍:
如果后端返回的是PDF文件在服务器上的路径,直接访问该路径即可在浏览器中预览PDF文件。例如,后端返回路径http://example.com/path/to/file.pdf
,在前端可以通过如下方式实现预览:
<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文件。此时,需要对接口的响应头进行设置:
Content-Disposition: inline;filename=<pdf的文件名>
Content-Disposition
有两个值:attachment
表示下载文件,inline
表示内嵌显示。上述设置是告诉浏览器,当前接口返回的文件流是PDF格式,且需要内嵌显示,即预览。假设后端接口为/api/getPdfStream
,在Vue中可以这样调用:
export function getPdfStream() {
return axios.get('/api/getPdfStream', {
responseType: 'arraybuffer',
headers: {
'Content-Disposition': 'inline;filename=example.pdf'
}
})
}
在组件中使用:
<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>
static
文件夹(若已存在则无需重复创建),在static
下新建pdf
文件夹,并将解压后的PDF.js文件放在该目录中。copy-webpack-plugin
插件将static
文件夹下的静态资源复制到dist
目录,确保开启本地服务或上线后能访问到静态资源。首先安装copy-webpack-plugin
:npm install copy-webpack-plugin --save-dev
然后在webpack.config.js
中进行配置:
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
// 其他配置项
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from:'static',
to: 'static'
}
]
})
]
}
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>假设我们正在开发一个文档管理系统,用户需要在系统中预览合同文件(以PDF格式存储)。后端提供了一个接口/api/contracts/{id}/pdf
,该接口根据合同ID返回对应的PDF文件流。
ContractPreview.vue
组件中:<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>
ContractPreview.vue
组件中:<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>
ContractPreview.vue
组件中:<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 删除。